github.com/consensys/gnark-crypto@v0.14.0/internal/generator/ecc/template/point.go.tmpl (about) 1 2 {{ $TAffine := print (toUpper .PointName) "Affine" }} 3 {{ $TJacobian := print (toUpper .PointName) "Jac" }} 4 {{ $TJacobianExtended := print (toLower .PointName) "JacExtended" }} 5 {{ $TProjective := print (toLower .PointName) "Proj" }} 6 7 8 import ( 9 {{- if eq .PointName "g2"}} 10 "crypto/rand" 11 {{- end}} 12 "math/big" 13 "runtime" 14 15 {{- if .GLV}} 16 "github.com/consensys/gnark-crypto/ecc" 17 {{- end}} 18 "github.com/consensys/gnark-crypto/internal/parallel" 19 "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" 20 {{- if or (eq .CoordType "fptower.E2") (eq .CoordType "fptower.E4") }} 21 "github.com/consensys/gnark-crypto/ecc/{{.Name}}/internal/fptower" 22 {{else}} 23 "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp" 24 {{- end}} 25 ) 26 27 28 // {{ $TAffine }} is a point in affine coordinates (x,y) 29 type {{ $TAffine }} struct { 30 X, Y {{.CoordType}} 31 } 32 33 // {{ $TJacobian }} is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) 34 type {{ $TJacobian }} struct { 35 X, Y, Z {{.CoordType}} 36 } 37 38 // {{ $TJacobianExtended }} is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) 39 type {{ $TJacobianExtended }} struct { 40 X, Y, ZZ, ZZZ {{.CoordType}} 41 } 42 43 {{- if .Projective}} 44 // {{ $TProjective }} point in projective coordinates 45 type {{ $TProjective }} struct { 46 x, y, z {{.CoordType}} 47 } 48 {{- end}} 49 50 51 52 // ------------------------------------------------------------------------------------------------- 53 // Affine coordinates 54 55 // Set sets p to a in affine coordinates. 56 func (p *{{ $TAffine }}) Set(a *{{ $TAffine }}) *{{ $TAffine }} { 57 p.X, p.Y = a.X, a.Y 58 return p 59 } 60 61 // setInfinity sets p to the infinity point, which is encoded as (0,0). 62 // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). 63 func (p *{{ $TAffine }}) setInfinity() *{{ $TAffine }} { 64 p.X.SetZero() 65 p.Y.SetZero() 66 return p 67 } 68 69 // ScalarMultiplication computes and returns p = [s]a 70 // where p and a are affine points. 71 func (p *{{ $TAffine }}) ScalarMultiplication(a *{{ $TAffine }}, s *big.Int) *{{ $TAffine }} { 72 var _p {{ $TJacobian }} 73 _p.FromAffine(a) 74 {{- if .GLV}} 75 _p.mulGLV(&_p, s) 76 {{- else }} 77 _p.mulWindowed(&_p, s) 78 {{- end }} 79 p.FromJacobian(&_p) 80 return p 81 } 82 83 // ScalarMultiplicationBase computes and returns p = [s]g 84 // where g is the affine point generating the prime subgroup. 85 func (p *{{ $TAffine }}) ScalarMultiplicationBase(s *big.Int) *{{ $TAffine }} { 86 var _p {{ $TJacobian }} 87 {{- if .GLV}} 88 _p.mulGLV(&{{ toLower .PointName}}Gen, s) 89 {{- else }} 90 _p.mulWindowed(&{{ toLower .PointName}}Gen, s) 91 {{- end }} 92 p.FromJacobian(&_p) 93 return p 94 } 95 96 97 // Add adds two points in affine coordinates. 98 // It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. 99 // 100 // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl 101 func (p *{{ $TAffine }}) Add(a, b *{{ $TAffine }}) *{{ $TAffine }} { 102 var q {{ $TJacobian }} 103 // a is infinity, return b 104 if a.IsInfinity() { 105 p.Set(b) 106 return p 107 } 108 // b is infinity, return a 109 if b.IsInfinity() { 110 p.Set(a) 111 return p 112 } 113 if a.X.Equal(&b.X) { 114 // if b == a, we double instead 115 if a.Y.Equal(&b.Y) { 116 q.DoubleMixed(a) 117 return p.FromJacobian(&q) 118 } else { 119 // if b == -a, we return 0 120 return p.setInfinity() 121 } 122 } 123 var H, HH, I, J, r, V {{.CoordType}} 124 H.Sub(&b.X, &a.X) 125 HH.Square(&H) 126 I.Double(&HH).Double(&I) 127 J.Mul(&H, &I) 128 r.Sub(&b.Y, &a.Y) 129 r.Double(&r) 130 V.Mul(&a.X, &I) 131 q.X.Square(&r). 132 Sub(&q.X, &J). 133 Sub(&q.X, &V). 134 Sub(&q.X, &V) 135 q.Y.Sub(&V, &q.X). 136 Mul(&q.Y, &r) 137 J.Mul(&a.Y, &J).Double(&J) 138 q.Y.Sub(&q.Y, &J) 139 q.Z.Double(&H) 140 141 return p.FromJacobian(&q) 142 } 143 144 // Double doubles a point in affine coordinates. 145 // It converts the point to Jacobian coordinates, doubles it using Jacobian 146 // addition with a.Z=1, and converts it back to affine coordinates. 147 // 148 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl 149 func (p *{{ $TAffine }}) Double(a *{{ $TAffine }}) *{{ $TAffine }} { 150 var q {{ $TJacobian }} 151 q.FromAffine(a) 152 q.DoubleMixed(a) 153 p.FromJacobian(&q) 154 return p 155 } 156 157 // Sub subtracts two points in affine coordinates. 158 // It uses a similar approach to Add, but negates the second point before adding. 159 func (p *{{ $TAffine }}) Sub(a, b *{{ $TAffine }}) *{{ $TAffine }} { 160 var bneg {{ $TAffine }} 161 bneg.Neg(b) 162 p.Add(a, &bneg) 163 return p 164 } 165 166 // Equal tests if two points in affine coordinates are equal. 167 func (p *{{ $TAffine }}) Equal(a *{{ $TAffine }}) bool { 168 return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) 169 } 170 171 172 // Neg sets p to the affine negative point -a = (a.X, -a.Y). 173 func (p *{{ $TAffine }}) Neg(a *{{ $TAffine }}) *{{ $TAffine }} { 174 p.X = a.X 175 p.Y.Neg(&a.Y) 176 return p 177 } 178 179 // FromJacobian converts a point p1 from Jacobian to affine coordinates. 180 func (p *{{ $TAffine }}) FromJacobian(p1 *{{ $TJacobian }}) *{{ $TAffine }} { 181 182 var a, b {{.CoordType}} 183 184 if p1.Z.IsZero() { 185 p.X.SetZero() 186 p.Y.SetZero() 187 return p 188 } 189 190 a.Inverse(&p1.Z) 191 b.Square(&a) 192 p.X.Mul(&p1.X, &b) 193 p.Y.Mul(&p1.Y, &b).Mul(&p.Y, &a) 194 195 return p 196 } 197 198 // String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. 199 func (p *{{ $TAffine }}) String() string { 200 if p.IsInfinity() { 201 return "O" 202 } 203 return "E([" + p.X.String() + "," + p.Y.String() + "])" 204 } 205 206 // IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). 207 // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). 208 func (p *{{ $TAffine }}) IsInfinity() bool { 209 return p.X.IsZero() && p.Y.IsZero() 210 } 211 212 // IsOnCurve returns true if the affine point p in on the curve. 213 func (p *{{ $TAffine }}) IsOnCurve() bool { 214 var point {{ $TJacobian }} 215 point.FromAffine(p) 216 return point.IsOnCurve() // call this function to handle infinity point 217 } 218 219 // IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. 220 func (p *{{ $TAffine }}) IsInSubGroup() bool { 221 var _p {{ $TJacobian }} 222 _p.FromAffine(p) 223 return _p.IsInSubGroup() 224 } 225 226 227 // ------------------------------------------------------------------------------------------------- 228 // Jacobian coordinates 229 230 // Set sets p to a in Jacobian coordinates. 231 func (p *{{ $TJacobian }}) Set(q *{{ $TJacobian }}) *{{ $TJacobian }} { 232 p.X, p.Y, p.Z = q.X, q.Y, q.Z 233 return p 234 } 235 236 // Equal tests if two points in Jacobian coordinates are equal. 237 func (p *{{ $TJacobian }}) Equal(q *{{ $TJacobian }}) bool { 238 // If one point is infinity, the other must also be infinity. 239 if p.Z.IsZero() { 240 return q.Z.IsZero() 241 } 242 // If the other point is infinity, return false since we can't 243 // the following checks would be incorrect. 244 if q.Z.IsZero() { 245 return false 246 } 247 248 var pZSquare, aZSquare {{.CoordType}} 249 pZSquare.Square(&p.Z) 250 aZSquare.Square(&q.Z) 251 252 var lhs, rhs {{.CoordType}} 253 lhs.Mul(&p.X, &aZSquare) 254 rhs.Mul(&q.X, &pZSquare) 255 if !lhs.Equal(&rhs) { 256 return false 257 } 258 lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) 259 rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) 260 261 return lhs.Equal(&rhs) 262 } 263 264 // Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). 265 func (p *{{ $TJacobian }}) Neg(q *{{ $TJacobian }}) *{{ $TJacobian }} { 266 *p = *q 267 p.Y.Neg(&q.Y) 268 return p 269 } 270 271 // AddAssign sets p to p+a in Jacobian coordinates. 272 // 273 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl 274 func (p *{{ $TJacobian }}) AddAssign(q *{{ $TJacobian }}) *{{ $TJacobian }} { 275 276 // p is infinity, return q 277 if p.Z.IsZero() { 278 p.Set(q) 279 return p 280 } 281 282 // q is infinity, return p 283 if q.Z.IsZero() { 284 return p 285 } 286 287 var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V {{.CoordType}} 288 Z1Z1.Square(&q.Z) 289 Z2Z2.Square(&p.Z) 290 U1.Mul(&q.X, &Z2Z2) 291 U2.Mul(&p.X, &Z1Z1) 292 S1.Mul(&q.Y, &p.Z). 293 Mul(&S1, &Z2Z2) 294 S2.Mul(&p.Y, &q.Z). 295 Mul(&S2, &Z1Z1) 296 297 // if p == q, we double instead 298 if U1.Equal(&U2) && S1.Equal(&S2) { 299 return p.DoubleAssign() 300 } 301 302 H.Sub(&U2, &U1) 303 I.Double(&H). 304 Square(&I) 305 J.Mul(&H, &I) 306 r.Sub(&S2, &S1).Double(&r) 307 V.Mul(&U1, &I) 308 p.X.Square(&r). 309 Sub(&p.X, &J). 310 Sub(&p.X, &V). 311 Sub(&p.X, &V) 312 p.Y.Sub(&V, &p.X). 313 Mul(&p.Y, &r) 314 S1.Mul(&S1, &J).Double(&S1) 315 p.Y.Sub(&p.Y, &S1) 316 p.Z.Add(&p.Z, &q.Z) 317 p.Z.Square(&p.Z). 318 Sub(&p.Z, &Z1Z1). 319 Sub(&p.Z, &Z2Z2). 320 Mul(&p.Z, &H) 321 322 return p 323 } 324 325 // SubAssign sets p to p-a in Jacobian coordinates. 326 // It uses a similar approach to AddAssign, but negates the point a before adding. 327 func (p *{{ $TJacobian }}) SubAssign(q *{{ $TJacobian }}) *{{ $TJacobian }} { 328 var tmp {{ $TJacobian }} 329 tmp.Set(q) 330 tmp.Y.Neg(&tmp.Y) 331 p.AddAssign(&tmp) 332 return p 333 } 334 335 // Double sets p to [2]q in Jacobian coordinates. 336 // 337 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 338 func (p *{{ $TJacobian }}) DoubleMixed(a *{{ $TAffine }}) *{{ $TJacobian }} { 339 var XX, YY, YYYY, S, M, T {{.CoordType}} 340 XX.Square(&a.X) 341 YY.Square(&a.Y) 342 YYYY.Square(&YY) 343 S.Add(&a.X, &YY). 344 Square(&S). 345 Sub(&S, &XX). 346 Sub(&S, &YYYY). 347 Double(&S) 348 M.Double(&XX). 349 Add(&M, &XX) // -> + A, but A=0 here 350 T.Square(&M). 351 Sub(&T, &S). 352 Sub(&T, &S) 353 p.X.Set(&T) 354 p.Y.Sub(&S, &T). 355 Mul(&p.Y, &M) 356 YYYY.Double(&YYYY). 357 Double(&YYYY). 358 Double(&YYYY) 359 p.Y.Sub(&p.Y, &YYYY) 360 p.Z.Double(&a.Y) 361 362 return p 363 } 364 365 // AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. 366 // 367 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl 368 func (p *{{ $TJacobian }}) AddMixed(a *{{ $TAffine }}) *{{ $TJacobian }} { 369 370 //if a is infinity return p 371 if a.IsInfinity() { 372 return p 373 } 374 // p is infinity, return a 375 if p.Z.IsZero() { 376 p.X = a.X 377 p.Y = a.Y 378 p.Z.SetOne() 379 return p 380 } 381 382 var Z1Z1, U2, S2, H, HH, I, J, r, V {{.CoordType}} 383 Z1Z1.Square(&p.Z) 384 U2.Mul(&a.X, &Z1Z1) 385 S2.Mul(&a.Y, &p.Z). 386 Mul(&S2, &Z1Z1) 387 388 // if p == a, we double instead 389 if U2.Equal(&p.X) && S2.Equal(&p.Y) { 390 return p.DoubleMixed(a) 391 } 392 393 H.Sub(&U2, &p.X) 394 HH.Square(&H) 395 I.Double(&HH).Double(&I) 396 J.Mul(&H, &I) 397 r.Sub(&S2, &p.Y).Double(&r) 398 V.Mul(&p.X, &I) 399 p.X.Square(&r). 400 Sub(&p.X, &J). 401 Sub(&p.X, &V). 402 Sub(&p.X, &V) 403 J.Mul(&J, &p.Y).Double(&J) 404 p.Y.Sub(&V, &p.X). 405 Mul(&p.Y, &r) 406 p.Y.Sub(&p.Y, &J) 407 p.Z.Add(&p.Z, &H) 408 p.Z.Square(&p.Z). 409 Sub(&p.Z, &Z1Z1). 410 Sub(&p.Z, &HH) 411 412 return p 413 } 414 415 // Double sets p to [2]q in Jacobian coordinates. 416 // 417 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 418 func (p *{{ $TJacobian }}) Double(q *{{ $TJacobian }}) *{{ $TJacobian }} { 419 p.Set(q) 420 p.DoubleAssign() 421 return p 422 } 423 424 // DoubleAssign doubles p in Jacobian coordinates. 425 // 426 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 427 func (p *{{ $TJacobian }}) DoubleAssign() *{{ $TJacobian }} { 428 429 var XX, YY, YYYY, ZZ, S, M, T {{.CoordType}} 430 431 XX.Square(&p.X) 432 YY.Square(&p.Y) 433 YYYY.Square(&YY) 434 ZZ.Square(&p.Z) 435 S.Add(&p.X, &YY) 436 S.Square(&S). 437 Sub(&S, &XX). 438 Sub(&S, &YYYY). 439 Double(&S) 440 M.Double(&XX).Add(&M, &XX) 441 p.Z.Add(&p.Z, &p.Y). 442 Square(&p.Z). 443 Sub(&p.Z, &YY). 444 Sub(&p.Z, &ZZ) 445 T.Square(&M) 446 p.X = T 447 T.Double(&S) 448 p.X.Sub(&p.X, &T) 449 p.Y.Sub(&S, &p.X). 450 Mul(&p.Y, &M) 451 YYYY.Double(&YYYY).Double(&YYYY).Double(&YYYY) 452 p.Y.Sub(&p.Y, &YYYY) 453 454 return p 455 } 456 457 // ScalarMultiplication computes and returns p = [s]a 458 // where p and a are Jacobian points. 459 {{- if .GLV}} 460 // using the GLV technique. 461 // see https://www.iacr.org/archive/crypto2001/21390189.pdf 462 {{- else }} 463 // using a 2-bits windowed double-and-add method. 464 {{- end }} 465 func (p *{{ $TJacobian }}) ScalarMultiplication(q *{{ $TJacobian }}, s *big.Int) *{{ $TJacobian }} { 466 {{- if .GLV}} 467 return p.mulGLV(q, s) 468 {{- else }} 469 return p.mulWindowed(q, s) 470 {{- end }} 471 } 472 473 // ScalarMultiplicationBase computes and returns p = [s]g 474 // where g is the prime subgroup generator. 475 func (p *{{ $TJacobian }}) ScalarMultiplicationBase(s *big.Int) *{{ $TJacobian }} { 476 {{- if .GLV}} 477 return p.mulGLV(&{{ toLower .PointName }}Gen, s) 478 {{- else }} 479 _p.mulWindowed(&{{ toLower .PointName }}Gen, s) 480 {{- end }} 481 482 } 483 484 // String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. 485 func (p *{{ $TJacobian }}) String() string { 486 _p := {{ $TAffine }}{} 487 _p.FromJacobian(p) 488 return _p.String() 489 } 490 491 // FromAffine converts a point a from affine to Jacobian coordinates. 492 func (p *{{ $TJacobian }}) FromAffine(a *{{ $TAffine }}) *{{ $TJacobian }} { 493 if a.IsInfinity() { 494 p.Z.SetZero() 495 p.X.SetOne() 496 p.Y.SetOne() 497 return p 498 } 499 p.Z.SetOne() 500 p.X.Set(&a.X) 501 p.Y.Set(&a.Y) 502 return p 503 } 504 505 // IsOnCurve returns true if the Jacobian point p in on the curve. 506 func (p *{{ $TJacobian }}) IsOnCurve() bool { 507 var left, right, tmp, ZZ {{.CoordType}} 508 left.Square(&p.Y) 509 right.Square(&p.X).Mul(&right, &p.X) 510 ZZ.Square(&p.Z) 511 tmp.Square(&ZZ).Mul(&tmp, &ZZ) 512 {{- if eq .PointName "g1"}} 513 {{- if or (eq .Name "bls12-381") (eq .Name "bls24-317") (eq .Name "bw6-633")}} 514 // Mul tmp by bCurveCoeff=4 515 tmp.Double(&tmp).Double(&tmp) 516 {{- else if eq .Name "bn254"}} 517 // Mul tmp by bCurveCoeff=3 518 fp.MulBy3(&tmp) 519 {{- else if eq .Name "bw6-761"}} 520 // Mul tmp by bCurveCoeff=-1 521 tmp.Neg(&tmp) 522 {{- else if or (eq .Name "bls12-377") (eq .Name "bls12-378") (eq .Name "bls24-315") (eq .Name "bw6-756")}} 523 // Mul tmp by bCurveCoeff=1 (nothing to do) 524 {{- else}} 525 tmp.Mul(&tmp, &bCurveCoeff) 526 {{- end}} 527 {{- else}} 528 {{- if or (eq .Name "bls12-377") (eq .Name "bls12-381") (eq .Name "bn254") (eq .Name "bls24-315") (eq .Name "bls24-317")}} 529 tmp.MulBybTwistCurveCoeff(&tmp) 530 {{- else if eq .Name "bw6-761"}} 531 // Mul tmp by bTwistCurveCoeff=4 532 tmp.Double(&tmp).Double(&tmp) 533 {{- else if eq .Name "bw6-633"}} 534 // Mul tmp by bTwistCurveCoeff=8 535 tmp.Double(&tmp).Double(&tmp).Double(&tmp) 536 {{- else}} 537 tmp.Mul(&tmp, &bTwistCurveCoeff) 538 {{- end}} 539 {{- end}} 540 right.Add(&right, &tmp) 541 return left.Equal(&right) 542 } 543 544 545 546 {{- if or (eq .Name "bn254") (eq .Name "secp256k1")}} 547 {{- if eq .PointName "g1"}} 548 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 549 // the curve is of prime order i.e. E(𝔽p) is the full group 550 // so we just check that the point is on the curve. 551 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 552 553 return p.IsOnCurve() 554 555 } 556 {{else if eq .PointName "g2"}} 557 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 558 // https://eprint.iacr.org/2022/348.pdf, sec. 3 and 5.1 559 // [r]P == 0 <==> [x₀+1]P + ψ([x₀]P) + ψ²([x₀]P) = ψ³([2x₀]P) 560 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 561 var a, b, c, res G2Jac 562 a.ScalarMultiplication(p, &xGen) 563 b.psi(&a) 564 a.AddAssign(p) 565 res.psi(&b) 566 c.Set(&res). 567 AddAssign(&b). 568 AddAssign(&a) 569 res.psi(&res). 570 Double(&res). 571 SubAssign(&c) 572 573 return res.IsOnCurve() && res.Z.IsZero() 574 } 575 {{- end}} 576 {{else if or (eq .Name "bw6-761") (eq .Name "bw6-756")}} 577 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 578 {{ if .GLV}} 579 // Z[r,0]+Z[-lambda{{ $TAffine }}, 1] is the kernel 580 // of (u,v)->u+lambda{{ $TAffine }}v mod r. Expressing r, lambda{{ $TAffine }} as 581 // polynomials in x, a short vector of this Zmodule is 582 // (x+1), (x³-x²+1). So we check that (x+1)p+(x³-x²+1)ϕ(p) 583 // is the infinity. 584 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 585 586 var res, phip {{ $TJacobian }} 587 phip.phi(p) 588 res.ScalarMultiplication(&phip, &xGen). 589 SubAssign(&phip). 590 ScalarMultiplication(&res, &xGen). 591 ScalarMultiplication(&res, &xGen). 592 AddAssign(&phip) 593 594 phip.ScalarMultiplication(p, &xGen).AddAssign(p).AddAssign(&res) 595 596 return phip.IsOnCurve() && phip.Z.IsZero() 597 {{ else}} 598 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 599 600 var res {{ $TJacobian }} 601 res.ScalarMultiplication(p, fr.Modulus()) 602 return res.IsOnCurve() && res.Z.IsZero() 603 {{ end}} 604 605 } 606 {{else if eq .Name "bw6-633"}} 607 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 608 {{ if .GLV}} 609 // 3r P = (x+1)ϕ(P) + (-x^5 + x⁴ + x)P 610 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 611 612 var uP, u4P, u5P, q, r {{ $TJacobian }} 613 uP.ScalarMultiplication(p, &xGen) 614 u4P.ScalarMultiplication(&uP, &xGen). 615 ScalarMultiplication(&u4P, &xGen). 616 ScalarMultiplication(&u4P, &xGen) 617 u5P.ScalarMultiplication(&u4P, &xGen) 618 q.Set(p).SubAssign(&uP) 619 r.phi(&q).SubAssign(&uP). 620 AddAssign(&u4P). 621 AddAssign(&u5P) 622 623 {{ else}} 624 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 625 626 var r {{ $TJacobian }} 627 r.ScalarMultiplication(p, fr.Modulus()) 628 {{ end}} 629 return r.IsOnCurve() && r.Z.IsZero() 630 } 631 {{else if or (eq .Name "bls24-315") (eq .Name "bls24-317")}} 632 {{- if eq .PointName "g1"}} 633 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 634 {{ if .GLV}} 635 // Z[r,0]+Z[-lambda{{ $TAffine }}, 1] is the kernel 636 // of (u,v)->u+lambda{{ $TAffine }}v mod r. Expressing r, lambda{{ $TAffine }} as 637 // polynomials in x, a short vector of this Zmodule is 638 // 1, x⁴. So we check that p+x⁴ϕ(p) 639 // is the infinity. 640 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 641 642 var res {{ $TJacobian }} 643 res.phi(p). 644 ScalarMultiplication(&res, &xGen). 645 ScalarMultiplication(&res, &xGen). 646 ScalarMultiplication(&res, &xGen). 647 ScalarMultiplication(&res, &xGen). 648 AddAssign(p) 649 {{ else}} 650 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 651 652 var res {{ $TJacobian }} 653 res.ScalarMultiplication(p, fr.Modulus()) 654 return res.IsOnCurve() && res.Z.IsZero() 655 {{ end}} 656 657 return res.IsOnCurve() && res.Z.IsZero() 658 659 } 660 {{else if eq .PointName "g2"}} 661 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 662 // https://eprint.iacr.org/2021/1130.pdf, sec.4 663 // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2 664 // ψ(p) = [x₀]P 665 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 666 var res, tmp {{ $TJacobian }} 667 tmp.psi(p) 668 res.ScalarMultiplication(p, &xGen). 669 {{ if eq .Name "bls24-315"}} 670 AddAssign(&tmp) 671 {{ else }} 672 SubAssign(&tmp) 673 {{ end }} 674 675 return res.IsOnCurve() && res.Z.IsZero() 676 677 } 678 {{- end}} 679 {{else}} 680 {{- if eq .PointName "g1"}} 681 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 682 // Z[r,0]+Z[-lambda{{ $TAffine }}, 1] is the kernel 683 // of (u,v)->u+lambda{{ $TAffine }}v mod r. Expressing r, lambda{{ $TAffine }} as 684 // polynomials in x, a short vector of this Zmodule is 685 // 1, x². So we check that p+x²ϕ(p) 686 // is the infinity. 687 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 688 689 var res {{ $TJacobian }} 690 {{ if .GLV}} 691 res.phi(p). 692 ScalarMultiplication(&res, &xGen). 693 ScalarMultiplication(&res, &xGen). 694 AddAssign(p) 695 {{ else}} 696 res.ScalarMultiplication(p, fr.Modulus()) 697 {{ end}} 698 699 return res.IsOnCurve() && res.Z.IsZero() 700 701 } 702 {{else if eq .PointName "g2"}} 703 {{if eq .Name "bls12-381"}} 704 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 705 // https://eprint.iacr.org/2021/1130.pdf, sec.4 706 // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2 707 // ψ(p) = [x₀]P 708 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 709 var res, tmp {{ $TJacobian }} 710 tmp.psi(p) 711 res.ScalarMultiplication(p, &xGen). 712 AddAssign(&tmp) 713 714 return res.IsOnCurve() && res.Z.IsZero() 715 } 716 {{else if or (eq .Name "bls12-377") (eq .Name "bls12-378")}} 717 // https://eprint.iacr.org/2021/1130.pdf, sec.4 718 // and https://eprint.iacr.org/2022/352.pdf, sec. 4.2 719 // ψ(p) = [x₀]P 720 func (p *{{ $TJacobian }}) IsInSubGroup() bool { 721 var res, tmp {{ $TJacobian }} 722 tmp.psi(p) 723 res.ScalarMultiplication(p, &xGen). 724 SubAssign(&tmp) 725 726 return res.IsOnCurve() && res.Z.IsZero() 727 } 728 {{- end}} 729 {{- end}} 730 {{- end}} 731 732 733 // mulWindowed computes the 2-bits windowed double-and-add scalar 734 // multiplication p=[s]q in Jacobian coordinates. 735 func (p *{{ $TJacobian }}) mulWindowed(q *{{ $TJacobian }}, s *big.Int) *{{ $TJacobian }} { 736 737 var res {{ $TJacobian }} 738 var ops [3]{{ $TJacobian }} 739 740 ops[0].Set(q) 741 if s.Sign() == -1 { 742 ops[0].Neg(&ops[0]) 743 } 744 res.Set(&{{ toLower .PointName}}Infinity) 745 ops[1].Double(&ops[0]) 746 ops[2].Set(&ops[0]).AddAssign(&ops[1]) 747 748 b := s.Bytes() 749 for i := range b { 750 w := b[i] 751 mask := byte(0xc0) 752 for j := 0; j < 4; j++ { 753 res.DoubleAssign().DoubleAssign() 754 c := (w & mask) >> (6 - 2*j) 755 if c != 0 { 756 res.AddAssign(&ops[c-1]) 757 } 758 mask = mask >> 2 759 } 760 } 761 p.Set(&res) 762 763 return p 764 765 } 766 767 {{ if eq .CoordType "fptower.E2" }} 768 // psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map. 769 func (p *{{ $TJacobian }}) psi(q *{{ $TJacobian }}) *{{ $TJacobian }} { 770 p.Set(q) 771 p.X.Conjugate(&p.X).Mul(&p.X, &endo.u) 772 p.Y.Conjugate(&p.Y).Mul(&p.Y, &endo.v) 773 p.Z.Conjugate(&p.Z) 774 return p 775 } 776 {{ else if eq .CoordType "fptower.E4"}} 777 // psi sets p to ψ(q) = u o π o u⁻¹ where u:E'→E is the isomorphism from the twist to the curve E and π is the Frobenius map. 778 func (p *{{ $TJacobian }}) psi(q *{{ $TJacobian }}) *{{ $TJacobian }} { 779 p.Set(q) 780 p.X.Frobenius(&p.X).Mul(&p.X, &endo.u) 781 p.Y.Frobenius(&p.Y).Mul(&p.Y, &endo.v) 782 p.Z.Frobenius(&p.Z) 783 return p 784 } 785 {{ end }} 786 787 {{ if .GLV}} 788 789 // phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), 790 // where w is a third root of unity. 791 func (p *{{ $TJacobian }}) phi(q *{{ $TJacobian }}) *{{ $TJacobian }} { 792 p.Set(q) 793 {{- if or (eq .CoordType "fptower.E2" ) (eq .CoordType "fptower.E4" )}} 794 p.X.MulByElement(&p.X, &thirdRootOne{{toUpper .PointName}}) 795 {{- else}} 796 p.X.Mul(&p.X, &thirdRootOne{{toUpper .PointName}}) 797 {{- end}} 798 return p 799 } 800 801 // mulGLV computes the scalar multiplication using a windowed-GLV method 802 // 803 // see https://www.iacr.org/archive/crypto2001/21390189.pdf 804 func (p *{{ $TJacobian }}) mulGLV(q *{{ $TJacobian }}, s *big.Int) *{{ $TJacobian }} { 805 806 var table [15]{{ $TJacobian }} 807 var res {{ $TJacobian }} 808 var k1, k2 fr.Element 809 810 res.Set(&{{ toLower .PointName}}Infinity) 811 812 // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q 813 table[0].Set(q) 814 table[3].phi(q) 815 816 // split the scalar, modifies ±q, ϕ(q) accordingly 817 k := ecc.SplitScalar(s, &glvBasis) 818 819 if k[0].Sign() == -1 { 820 k[0].Neg(&k[0]) 821 table[0].Neg(&table[0]) 822 } 823 if k[1].Sign() == -1 { 824 k[1].Neg(&k[1]) 825 table[3].Neg(&table[3]) 826 } 827 828 // precompute table (2 bits sliding window) 829 // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 830 table[1].Double(&table[0]) 831 table[2].Set(&table[1]).AddAssign(&table[0]) 832 table[4].Set(&table[3]).AddAssign(&table[0]) 833 table[5].Set(&table[3]).AddAssign(&table[1]) 834 table[6].Set(&table[3]).AddAssign(&table[2]) 835 table[7].Double(&table[3]) 836 table[8].Set(&table[7]).AddAssign(&table[0]) 837 table[9].Set(&table[7]).AddAssign(&table[1]) 838 table[10].Set(&table[7]).AddAssign(&table[2]) 839 table[11].Set(&table[7]).AddAssign(&table[3]) 840 table[12].Set(&table[11]).AddAssign(&table[0]) 841 table[13].Set(&table[11]).AddAssign(&table[1]) 842 table[14].Set(&table[11]).AddAssign(&table[2]) 843 844 // bounds on the lattice base vectors guarantee that k1, k2 are len(r)/2 or len(r)/2+1 bits long max 845 // this is because we use a probabilistic scalar decomposition that replaces a division by a right-shift 846 k1 = k1.SetBigInt(&k[0]).Bits() 847 k2 = k2.SetBigInt(&k[1]).Bits() 848 849 // we don't target constant-timeness so we check first if we increase the bounds or not 850 maxBit := k1.BitLen() 851 if k2.BitLen() > maxBit { 852 maxBit = k2.BitLen() 853 } 854 hiWordIndex := (maxBit - 1) / 64 855 856 // loop starts from len(k1)/2 or len(k1)/2+1 due to the bounds 857 for i := hiWordIndex; i >= 0; i-- { 858 mask := uint64(3) << 62 859 for j := 0; j < 32; j++ { 860 res.Double(&res).Double(&res) 861 b1 := (k1[i] & mask) >> (62 - 2*j) 862 b2 := (k2[i] & mask) >> (62 - 2*j) 863 if b1|b2 != 0 { 864 s := (b2<<2 | b1) 865 res.AddAssign(&table[s-1]) 866 } 867 mask = mask >> 2 868 } 869 } 870 871 p.Set(&res) 872 return p 873 } 874 875 876 {{ end }} 877 878 {{ if .CofactorCleaning}} 879 880 // ClearCofactor maps a point in curve to r-torsion 881 func (p *{{ $TAffine }}) ClearCofactor(a *{{ $TAffine }}) *{{ $TAffine }} { 882 var _p {{$TJacobian}} 883 _p.FromAffine(a) 884 _p.ClearCofactor(&_p) 885 p.FromJacobian(&_p) 886 return p 887 } 888 889 {{- if eq .PointName "g1"}} 890 891 // ClearCofactor maps a point in E(Fp) to E(Fp)[r] 892 func (p *{{$TJacobian}}) ClearCofactor(q *{{$TJacobian}}) *{{$TJacobian}} { 893 {{- if or (eq .Name "bls12-381") (eq .Name "bls24-315")}} 894 // cf https://eprint.iacr.org/2019/403.pdf, 5 895 var res {{$TJacobian}} 896 res.ScalarMultiplication(q, &xGen).AddAssign(q) 897 p.Set(&res) 898 return p 899 {{else if or (eq .Name "bls12-377") (eq .Name "bls12-378") (eq .Name "bls24-317")}} 900 // cf https://eprint.iacr.org/2019/403.pdf, 5 901 var res {{$TJacobian}} 902 res.ScalarMultiplication(q, &xGen).Neg(&res).AddAssign(q) 903 p.Set(&res) 904 return p 905 {{else if eq .Name "bw6-761"}} 906 {{ if .GLV}} 907 // https://eprint.iacr.org/2020/351.pdf 908 var points [4]{{$TJacobian}} 909 points[0].Set(q) 910 points[1].ScalarMultiplication(q, &xGen) 911 points[2].ScalarMultiplication(&points[1], &xGen) 912 points[3].ScalarMultiplication(&points[2], &xGen) 913 914 var scalars [7]big.Int 915 scalars[0].SetInt64(103) 916 scalars[1].SetInt64(83) 917 scalars[2].SetInt64(40) 918 scalars[3].SetInt64(136) 919 920 scalars[4].SetInt64(7) 921 scalars[5].SetInt64(89) 922 scalars[6].SetInt64(130) 923 924 var p1, p2, tmp {{$TJacobian}} 925 p1.ScalarMultiplication(&points[3], &scalars[0]) 926 tmp.ScalarMultiplication(&points[2], &scalars[1]).Neg(&tmp) 927 p1.AddAssign(&tmp) 928 tmp.ScalarMultiplication(&points[1], &scalars[2]).Neg(&tmp) 929 p1.AddAssign(&tmp) 930 tmp.ScalarMultiplication(&points[0], &scalars[3]) 931 p1.AddAssign(&tmp) 932 933 p2.ScalarMultiplication(&points[2], &scalars[4]) 934 tmp.ScalarMultiplication(&points[1], &scalars[5]) 935 p2.AddAssign(&tmp) 936 tmp.ScalarMultiplication(&points[0], &scalars[6]) 937 p2.AddAssign(&tmp) 938 p2.phi(&p2) 939 940 p.Set(&p1).AddAssign(&p2) 941 {{ else}} 942 var c1 big.Int 943 c1.SetString("26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194876", 10) 944 p.ScalarMultiplication(q, &c1) 945 {{ end}} 946 947 return p 948 {{else if eq .Name "bw6-633"}} 949 {{ if .GLV}} 950 var uP, vP, wP, L0, L1, tmp {{$TJacobian}} 951 var v, one, uPlusOne, uMinusOne, d1, d2, ht big.Int 952 one.SetInt64(1) 953 uPlusOne.Add(&one, &xGen) 954 uMinusOne.Sub(&xGen, &one) 955 d1.SetInt64(13) 956 d2.SetInt64(5) 957 ht.SetInt64(7) 958 v.Mul(&xGen, &xGen).Add(&v, &one).Mul(&v, &uPlusOne) 959 960 uP.ScalarMultiplication(q, &xGen).Neg(&uP) 961 vP.Set(q).SubAssign(&uP). 962 ScalarMultiplication(&vP, &v) 963 wP.ScalarMultiplication(&vP, &uMinusOne).Neg(&wP). 964 AddAssign(&uP) 965 L0.ScalarMultiplication(&wP, &d1) 966 tmp.ScalarMultiplication(&vP, &ht) 967 L0.AddAssign(&tmp) 968 tmp.Double(q) 969 L0.AddAssign(&tmp) 970 L1.Set(&uP).AddAssign(q).ScalarMultiplication(&L1, &d1) 971 tmp.ScalarMultiplication(&vP, &d2) 972 L1.AddAssign(&tmp) 973 tmp.ScalarMultiplication(q, &ht) 974 L1.AddAssign(&tmp) 975 976 p.phi(&L1).AddAssign(&L0) 977 {{ else}} 978 var c1 big.Int 979 c1.SetString("516166855112631370346774477030598579858367278343565509012644853411927535599366632765988905418773", 10) 980 p.ScalarMultiplication(q, &c1) 981 {{ end}} 982 983 return p 984 {{else if eq .Name "bw6-756"}} 985 {{ if .GLV}} 986 var L0, L1, uP, u2P, u3P, tmp G1Jac 987 988 uP.ScalarMultiplication(q, &xGen) 989 u2P.ScalarMultiplication(&uP, &xGen) 990 u3P.ScalarMultiplication(&u2P, &xGen) 991 992 L0.Set(q).AddAssign(&u3P). 993 SubAssign(&u2P) 994 tmp.Set(q).AddAssign(&u2P). 995 SubAssign(&uP). 996 SubAssign(&uP). 997 Double(&tmp) 998 L0.SubAssign(&tmp). 999 SubAssign(q) 1000 1001 L1.Set(q).AddAssign(&uP) 1002 tmp.Set(&uP).SubAssign(q). 1003 Double(&tmp). 1004 SubAssign(&u2P) 1005 L1.AddAssign(&tmp). 1006 SubAssign(q) 1007 1008 p.phi(&L1). 1009 AddAssign(&L0) 1010 {{ else}} 1011 var c1 big.Int 1012 c1.SetString("605248206075306171568857128027361794400937215108643640003009340657451546212610770151705515081537938829431808196608", 10) 1013 p.ScalarMultiplication(q, &c1) 1014 {{ end}} 1015 1016 return p 1017 {{- end}} 1018 } 1019 {{ else }} 1020 1021 // ClearCofactor maps a point in curve to r-torsion 1022 func (p *{{$TJacobian}}) ClearCofactor(q *{{$TJacobian}}) *{{$TJacobian}} { 1023 {{- if eq .Name "bn254"}} 1024 // cf http://cacr.uwaterloo.ca/techreports/2011/cacr2011-26.pdf, 6.1 1025 var points [4]{{$TJacobian}} 1026 1027 points[0].ScalarMultiplication(q, &xGen) 1028 1029 points[1].Double(&points[0]). 1030 AddAssign(&points[0]). 1031 psi(&points[1]) 1032 1033 points[2].psi(&points[0]). 1034 psi(&points[2]) 1035 1036 points[3].psi(q).psi(&points[3]).psi(&points[3]) 1037 1038 var res {{$TJacobian}} 1039 res.Set(&g2Infinity) 1040 for i := 0; i < 4; i++ { 1041 res.AddAssign(&points[i]) 1042 } 1043 p.Set(&res) 1044 return p 1045 {{else if eq .Name "bls12-381"}} 1046 // https://eprint.iacr.org/2017/419.pdf, 4.1 1047 var xg, xxg, res, t G2Jac 1048 xg.ScalarMultiplication(q, &xGen).Neg(&xg) 1049 xxg.ScalarMultiplication(&xg, &xGen).Neg(&xxg) 1050 1051 res.Set(&xxg). 1052 SubAssign(&xg). 1053 SubAssign(q) 1054 1055 t.Set(&xg). 1056 SubAssign(q). 1057 psi(&t) 1058 1059 res.AddAssign(&t) 1060 1061 t.Double(q) 1062 t.X.MulByElement(&t.X, &thirdRootOneG1) 1063 1064 res.SubAssign(&t) 1065 1066 p.Set(&res) 1067 1068 return p 1069 1070 {{else if or (eq .Name "bls12-377") (eq .Name "bls12-378")}} 1071 // https://eprint.iacr.org/2017/419.pdf, 4.1 1072 var xg, xxg, res, t G2Jac 1073 xg.ScalarMultiplication(q, &xGen) 1074 xxg.ScalarMultiplication(&xg, &xGen) 1075 1076 res.Set(&xxg). 1077 SubAssign(&xg). 1078 SubAssign(q) 1079 1080 t.Set(&xg). 1081 SubAssign(q). 1082 psi(&t) 1083 1084 res.AddAssign(&t) 1085 1086 t.Double(q) 1087 t.X.MulByElement(&t.X, &thirdRootOneG1) 1088 1089 res.SubAssign(&t) 1090 1091 p.Set(&res) 1092 1093 return p 1094 1095 {{else if or (eq .Name "bls24-315") (eq .Name "bls24-317")}} 1096 // https://eprint.iacr.org/2017/419.pdf, section 4.2 1097 // multiply by (3x⁴-3)*cofacor 1098 {{ if eq .Name "bls24-315"}} 1099 var xg, xxg, xxxg, xxxxg, res, t G2Jac 1100 xg.ScalarMultiplication(q, &xGen).Neg(&xg).SubAssign(q) 1101 xxg.ScalarMultiplication(&xg, &xGen).Neg(&xxg) 1102 xxxg.ScalarMultiplication(&xxg, &xGen).Neg(&xxxg) 1103 xxxxg.ScalarMultiplication(&xxxg, &xGen).Neg(&xxxxg) 1104 {{ else }} 1105 var xg, xxg, xxxg, xxxxg, res, t G2Jac 1106 xg.ScalarMultiplication(q, &xGen).SubAssign(q) 1107 xxg.ScalarMultiplication(&xg, &xGen) 1108 xxxg.ScalarMultiplication(&xxg, &xGen) 1109 xxxxg.ScalarMultiplication(&xxxg, &xGen) 1110 {{ end }} 1111 1112 res.Set(&xxxxg). 1113 SubAssign(q) 1114 1115 t.Set(&xxxg). 1116 psi(&t). 1117 AddAssign(&res) 1118 1119 res.Set(&xxg). 1120 psi(&res). 1121 psi(&res). 1122 AddAssign(&t) 1123 1124 t.Set(&xg). 1125 psi(&t). 1126 psi(&t). 1127 psi(&t). 1128 AddAssign(&res) 1129 1130 res.Double(q). 1131 psi(&res). 1132 psi(&res). 1133 psi(&res). 1134 psi(&res). 1135 AddAssign(&t) 1136 1137 p.Set(&res) 1138 1139 return p 1140 {{else if eq .Name "bw6-761"}} 1141 1142 {{- if .GLV}} 1143 var points [4]{{$TJacobian}} 1144 points[0].Set(q) 1145 points[1].ScalarMultiplication(q, &xGen) 1146 points[2].ScalarMultiplication(&points[1], &xGen) 1147 points[3].ScalarMultiplication(&points[2], &xGen) 1148 1149 var scalars [7]big.Int 1150 scalars[0].SetInt64(103) 1151 scalars[1].SetInt64(83) 1152 scalars[2].SetInt64(143) 1153 scalars[3].SetInt64(27) 1154 1155 scalars[4].SetInt64(7) 1156 scalars[5].SetInt64(117) 1157 scalars[6].SetInt64(109) 1158 1159 var p1, p2, tmp {{$TJacobian}} 1160 p1.ScalarMultiplication(&points[3], &scalars[0]) 1161 tmp.ScalarMultiplication(&points[2], &scalars[1]).Neg(&tmp) 1162 p1.AddAssign(&tmp) 1163 tmp.ScalarMultiplication(&points[1], &scalars[2]).Neg(&tmp) 1164 p1.AddAssign(&tmp) 1165 tmp.ScalarMultiplication(&points[0], &scalars[3]) 1166 p1.AddAssign(&tmp) 1167 1168 p2.ScalarMultiplication(&points[2], &scalars[4]) 1169 tmp.ScalarMultiplication(&points[1], &scalars[5]).Neg(&tmp) 1170 p2.AddAssign(&tmp) 1171 tmp.ScalarMultiplication(&points[0], &scalars[6]).Neg(&tmp) 1172 p2.AddAssign(&tmp) 1173 p2.phi(&p2).phi(&p2) 1174 1175 p.Set(&p1).AddAssign(&p2) 1176 {{else}} 1177 var c2 big.Int 1178 c2.SetString("26642435879335816683987677701488073867751118270052650655942102502312977592501693353047140953112195348280268661194869", 10) 1179 p.ScalarMultiplication(q, &c2) 1180 {{end}} 1181 1182 return p 1183 {{else if eq .Name "bw6-633"}} 1184 {{- if .GLV}} 1185 var uP, u2P, u3P, u4P, u5P, xP, vP, wP, L0, L1, tmp {{$TJacobian}} 1186 var ht, d1, d3 big.Int 1187 ht.SetInt64(7) // negative 1188 d1.SetInt64(13) 1189 d3.SetInt64(5) // negative 1190 1191 uP.ScalarMultiplication(q, &xGen) // negative 1192 u2P.ScalarMultiplication(&uP, &xGen) 1193 u3P.ScalarMultiplication(&u2P, &xGen) // negative 1194 u4P.ScalarMultiplication(&u3P, &xGen) 1195 u5P.ScalarMultiplication(&u4P, &xGen) // negative 1196 vP.Set(&u2P).AddAssign(&uP). 1197 AddAssign(&u3P). 1198 Double(&vP). 1199 AddAssign(&u4P). 1200 AddAssign(q) 1201 wP.Set(&uP).SubAssign(&u4P).SubAssign(&u5P) 1202 xP.Set(q).AddAssign(&vP) 1203 L0.Set(&uP).SubAssign(q).ScalarMultiplication(&L0, &d1) 1204 tmp.ScalarMultiplication(&xP, &d3) 1205 L0.AddAssign(&tmp) 1206 tmp.ScalarMultiplication(q, &ht) // negative 1207 L0.SubAssign(&tmp) 1208 L1.ScalarMultiplication(&wP, &d1) 1209 tmp.ScalarMultiplication(&vP, &ht) 1210 L1.AddAssign(&tmp) 1211 tmp.ScalarMultiplication(q, &d3) 1212 L1.AddAssign(&tmp) 1213 1214 p.phi(&L1).AddAssign(&L0) 1215 {{else}} 1216 var c2 big.Int 1217 c2.SetString("516166855112631370346774477030598579858367278343565509012644853411927535599366632765988905418768", 10) 1218 p.ScalarMultiplication(q, &c2) 1219 {{end}} 1220 1221 return p 1222 {{else if eq .Name "bw6-756"}} 1223 1224 {{- if .GLV}} 1225 var L0, L1, uP, u2P, u3P, tmp G2Jac 1226 1227 uP.ScalarMultiplication(q, &xGen) 1228 u2P.ScalarMultiplication(&uP, &xGen) 1229 u3P.ScalarMultiplication(&u2P, &xGen) 1230 // ht=-2, hy=0 1231 // d1=1, d2=-1, d3=-1 1232 1233 L0.Set(q). 1234 AddAssign(&u2P). 1235 SubAssign(&uP) 1236 tmp.Set(&u2P). 1237 AddAssign(q). 1238 SubAssign(&uP). 1239 Double(&tmp) 1240 L1.Set(&u3P). 1241 SubAssign(&tmp) 1242 1243 p.phi(&L0). 1244 AddAssign(&L1) 1245 {{else}} 1246 var c2 big.Int 1247 c2.SetString("605248206075306171568857128027361794400937215108643640003009340657451546212610770151705515081537938829431808196609", 10) 1248 p.ScalarMultiplication(q, &c2) 1249 {{end}} 1250 1251 return p 1252 1253 {{- end}} 1254 } 1255 {{- end}} 1256 1257 1258 {{ end }} 1259 1260 {{ if eq .PointName "g1" }} 1261 // JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique 1262 // where a1 and a2 are affine points. 1263 func (p *{{$TJacobian}}) JointScalarMultiplication(a1, a2 *G1Affine, s1, s2 *big.Int) *{{$TJacobian}} { 1264 1265 var res, p1, p2 {{$TJacobian}} 1266 res.Set(&{{ toLower .PointName }}Infinity) 1267 p1.FromAffine(a1) 1268 p2.FromAffine(a2) 1269 1270 var table [15]{{$TJacobian}} 1271 1272 var k1, k2 big.Int 1273 if s1.Sign() == -1 { 1274 k1.Neg(s1) 1275 table[0].Neg(&p1) 1276 } else { 1277 k1.Set(s1) 1278 table[0].Set(&p1) 1279 } 1280 if s2.Sign() == -1 { 1281 k2.Neg(s2) 1282 table[3].Neg(&p2) 1283 } else { 1284 k2.Set(s2) 1285 table[3].Set(&p2) 1286 } 1287 1288 // precompute table (2 bits sliding window) 1289 table[1].Double(&table[0]) 1290 table[2].Set(&table[1]).AddAssign(&table[0]) 1291 table[4].Set(&table[3]).AddAssign(&table[0]) 1292 table[5].Set(&table[3]).AddAssign(&table[1]) 1293 table[6].Set(&table[3]).AddAssign(&table[2]) 1294 table[7].Double(&table[3]) 1295 table[8].Set(&table[7]).AddAssign(&table[0]) 1296 table[9].Set(&table[7]).AddAssign(&table[1]) 1297 table[10].Set(&table[7]).AddAssign(&table[2]) 1298 table[11].Set(&table[7]).AddAssign(&table[3]) 1299 table[12].Set(&table[11]).AddAssign(&table[0]) 1300 table[13].Set(&table[11]).AddAssign(&table[1]) 1301 table[14].Set(&table[11]).AddAssign(&table[2]) 1302 1303 var s [2]fr.Element 1304 s[0] = s[0].SetBigInt(&k1).Bits() 1305 s[1] = s[1].SetBigInt(&k2).Bits() 1306 1307 maxBit := k1.BitLen() 1308 if k2.BitLen() > maxBit { 1309 maxBit = k2.BitLen() 1310 } 1311 hiWordIndex := (maxBit - 1) / 64 1312 1313 for i := hiWordIndex; i >= 0; i-- { 1314 mask := uint64(3) << 62 1315 for j := 0; j < 32; j++ { 1316 res.Double(&res).Double(&res) 1317 b1 := (s[0][i] & mask) >> (62 - 2*j) 1318 b2 := (s[1][i] & mask) >> (62 - 2*j) 1319 if b1|b2 != 0 { 1320 s := (b2<<2 | b1) 1321 res.AddAssign(&table[s-1]) 1322 } 1323 mask = mask >> 2 1324 } 1325 } 1326 1327 p.Set(&res) 1328 return p 1329 1330 } 1331 1332 // JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique 1333 // where g is the prime subgroup generator. 1334 func (p *{{$TJacobian}}) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *{{$TJacobian}} { 1335 return p.JointScalarMultiplication(&g1GenAff, a, s1, s2) 1336 1337 } 1338 1339 {{ end }} 1340 1341 1342 // ------------------------------------------------------------------------------------------------- 1343 // extended Jacobian coordinates 1344 1345 // Set sets p to a in extended Jacobian coordinates. 1346 func (p *{{ $TJacobianExtended }}) Set(q *{{ $TJacobianExtended }}) *{{ $TJacobianExtended }} { 1347 p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ 1348 return p 1349 } 1350 1351 // setInfinity sets p to the infinity point (1,1,0,0). 1352 func (p *{{ $TJacobianExtended }}) setInfinity() *{{ $TJacobianExtended }} { 1353 p.X.SetOne() 1354 p.Y.SetOne() 1355 p.ZZ = {{.CoordType}}{} 1356 p.ZZZ = {{.CoordType}}{} 1357 return p 1358 } 1359 1360 // IsInfinity checks if the p is infinity, i.e. p.ZZ=0. 1361 func (p *{{ $TJacobianExtended }}) IsInfinity() bool { 1362 return p.ZZ.IsZero() 1363 } 1364 1365 // fromJacExtended converts an extended Jacobian point to an affine point. 1366 func (p *{{ $TAffine }}) fromJacExtended (q *{{ $TJacobianExtended }}) *{{ $TAffine }} { 1367 if q.ZZ.IsZero() { 1368 p.X = {{.CoordType}}{} 1369 p.Y = {{.CoordType}}{} 1370 return p 1371 } 1372 p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) 1373 p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) 1374 return p 1375 } 1376 1377 // fromJacExtended converts an extended Jacobian point to a Jacobian point. 1378 func (p *{{ $TJacobian }}) fromJacExtended(q *{{ $TJacobianExtended }}) *{{ $TJacobian }} { 1379 if q.ZZ.IsZero() { 1380 p.Set(&{{ toLower .PointName }}Infinity) 1381 return p 1382 } 1383 p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) 1384 p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) 1385 p.Z.Set(&q.ZZZ) 1386 return p 1387 } 1388 1389 // unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. 1390 func (p *{{ $TJacobian }}) unsafeFromJacExtended(q *{{ $TJacobianExtended }}) *{{ $TJacobian }} { 1391 p.X.Square(&q.ZZ).Mul(&p.X, &q.X) 1392 p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) 1393 p.Z = q.ZZZ 1394 return p 1395 } 1396 1397 // add sets p to p+q in extended Jacobian coordinates. 1398 // 1399 // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s 1400 func (p *{{ $TJacobianExtended }}) add(q *{{ $TJacobianExtended }}) *{{ $TJacobianExtended }} { 1401 //if q is infinity return p 1402 if q.ZZ.IsZero() { 1403 return p 1404 } 1405 // p is infinity, return q 1406 if p.ZZ.IsZero() { 1407 p.Set(q) 1408 return p 1409 } 1410 1411 var A, B, U1, U2, S1, S2 {{.CoordType}} 1412 1413 // p2: q, p1: p 1414 U2.Mul(&q.X, &p.ZZ) 1415 U1.Mul(&p.X, &q.ZZ) 1416 A.Sub(&U2, &U1) 1417 S2.Mul(&q.Y, &p.ZZZ) 1418 S1.Mul(&p.Y, &q.ZZZ) 1419 B.Sub(&S2, &S1) 1420 1421 if A.IsZero() { 1422 if B.IsZero() { 1423 return p.double(q) 1424 1425 } 1426 p.ZZ = {{.CoordType}}{} 1427 p.ZZZ = {{.CoordType}}{} 1428 return p 1429 } 1430 1431 1432 var P, R, PP, PPP, Q, V {{.CoordType}} 1433 P.Sub(&U2, &U1) 1434 R.Sub(&S2, &S1) 1435 PP.Square(&P) 1436 PPP.Mul(&P, &PP) 1437 Q.Mul(&U1, &PP) 1438 V.Mul(&S1, &PPP) 1439 1440 p.X.Square(&R). 1441 Sub(&p.X, &PPP). 1442 Sub(&p.X, &Q). 1443 Sub(&p.X, &Q) 1444 p.Y.Sub(&Q, &p.X). 1445 Mul(&p.Y, &R). 1446 Sub(&p.Y, &V) 1447 p.ZZ.Mul(&p.ZZ, &q.ZZ). 1448 Mul(&p.ZZ, &PP) 1449 p.ZZZ.Mul(&p.ZZZ, &q.ZZZ). 1450 Mul(&p.ZZZ, &PPP) 1451 1452 return p 1453 } 1454 1455 // double sets p to [2]q in Jacobian extended coordinates. 1456 // 1457 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 1458 // N.B.: since we consider any point on Z=0 as the point at infinity 1459 // this doubling formula works for infinity points as well. 1460 func (p *{{ $TJacobianExtended }}) double(q *{{ $TJacobianExtended }}) *{{ $TJacobianExtended }} { 1461 var U, V, W, S, XX, M {{.CoordType}} 1462 1463 U.Double(&q.Y) 1464 V.Square(&U) 1465 W.Mul(&U, &V) 1466 S.Mul(&q.X, &V) 1467 XX.Square(&q.X) 1468 M.Double(&XX). 1469 Add(&M, &XX) // -> + A, but A=0 here 1470 U.Mul(&W, &q.Y) 1471 1472 p.X.Square(&M). 1473 Sub(&p.X, &S). 1474 Sub(&p.X, &S) 1475 p.Y.Sub(&S, &p.X). 1476 Mul(&p.Y, &M). 1477 Sub(&p.Y, &U) 1478 p.ZZ.Mul(&V, &q.ZZ) 1479 p.ZZZ.Mul(&W, &q.ZZZ) 1480 1481 return p 1482 } 1483 1484 // addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. 1485 // 1486 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s 1487 func (p *{{ $TJacobianExtended }}) addMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} { 1488 {{ template "mAdd" dict "all" . "negate" false}} 1489 } 1490 1491 // subMixed works the same as addMixed, but negates a.Y. 1492 // 1493 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s 1494 func (p *{{ $TJacobianExtended }}) subMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} { 1495 {{ template "mAdd" dict "all" . "negate" true}} 1496 } 1497 1498 // doubleNegMixed works the same as double, but negates q.Y. 1499 func (p *{{ $TJacobianExtended }}) doubleNegMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} { 1500 {{ template "mDouble" dict "all" . "negate" true}} 1501 } 1502 1503 // doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. 1504 // 1505 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 1506 func (p *{{ $TJacobianExtended }}) doubleMixed(a *{{ $TAffine }}) *{{ $TJacobianExtended }} { 1507 {{ template "mDouble" dict "all" . "negate" false}} 1508 } 1509 1510 {{define "mDouble" }} 1511 var U, V, W, S, XX, M, S2, L {{.all.CoordType}} 1512 1513 U.Double(&a.Y) 1514 {{- if .negate}} 1515 U.Neg(&U) 1516 {{- end}} 1517 V.Square(&U) 1518 W.Mul(&U, &V) 1519 S.Mul(&a.X, &V) 1520 XX.Square(&a.X) 1521 M.Double(&XX). 1522 Add(&M, &XX) // -> + A, but A=0 here 1523 S2.Double(&S) 1524 L.Mul(&W, &a.Y) 1525 1526 p.X.Square(&M). 1527 Sub(&p.X, &S2) 1528 p.Y.Sub(&S, &p.X). 1529 Mul(&p.Y, &M). 1530 {{- if .negate}} 1531 Add(&p.Y, &L) 1532 {{- else}} 1533 Sub(&p.Y, &L) 1534 {{- end}} 1535 p.ZZ.Set(&V) 1536 p.ZZZ.Set(&W) 1537 1538 return p 1539 {{- end}} 1540 1541 {{define "mAdd" }} 1542 //if a is infinity return p 1543 if a.IsInfinity() { 1544 return p 1545 } 1546 // p is infinity, return a 1547 if p.ZZ.IsZero() { 1548 p.X = a.X 1549 {{- if .negate}} 1550 p.Y.Neg(&a.Y) 1551 {{- else }} 1552 p.Y = a.Y 1553 {{- end}} 1554 p.ZZ.SetOne() 1555 p.ZZZ.SetOne() 1556 return p 1557 } 1558 1559 var P, R {{.all.CoordType}} 1560 1561 // p2: a, p1: p 1562 P.Mul(&a.X, &p.ZZ) 1563 P.Sub(&P, &p.X) 1564 1565 R.Mul(&a.Y, &p.ZZZ) 1566 {{- if .negate}} 1567 R.Neg(&R) 1568 {{- end}} 1569 R.Sub(&R, &p.Y) 1570 1571 if P.IsZero() { 1572 if R.IsZero() { 1573 {{- if .negate}} 1574 return p.doubleNegMixed(a) 1575 {{ else }} 1576 return p.doubleMixed(a) 1577 {{- end}} 1578 1579 } 1580 p.ZZ = {{.all.CoordType}}{} 1581 p.ZZZ = {{.all.CoordType}}{} 1582 return p 1583 } 1584 1585 var PP, PPP, Q, Q2, RR, X3, Y3 {{.all.CoordType}} 1586 1587 1588 PP.Square(&P) 1589 PPP.Mul(&P, &PP) 1590 Q.Mul(&p.X, &PP) 1591 RR.Square(&R) 1592 X3.Sub(&RR, &PPP) 1593 Q2.Double(&Q) 1594 p.X.Sub(&X3, &Q2) 1595 Y3.Sub(&Q, &p.X).Mul(&Y3, &R) 1596 R.Mul(&p.Y, &PPP) 1597 p.Y.Sub(&Y3, &R) 1598 p.ZZ.Mul(&p.ZZ, &PP) 1599 p.ZZZ.Mul(&p.ZZZ, &PPP) 1600 1601 return p 1602 {{ end }} 1603 1604 1605 {{- if .Projective }} 1606 // ------------------------------------------------------------------------------------------------- 1607 // Homogenous projective coordinates 1608 1609 // Set sets p to a in projective coordinates. 1610 func (p *{{ $TProjective }}) Set(q *{{ $TProjective }}) *{{ $TProjective }} { 1611 p.x, p.y, p.z = q.x, q.y, q.z 1612 return p 1613 } 1614 1615 // Neg sets p to the projective negative point -q = (q.X, -q.Y). 1616 func (p *{{ $TProjective }}) Neg(q *{{ $TProjective }}) *{{ $TProjective }} { 1617 *p = *q 1618 p.y.Neg(&q.y) 1619 return p 1620 } 1621 1622 // FromAffine converts q in affine to p in projective coordinates. 1623 func (p *{{ $TProjective }}) FromAffine(a *{{ $TAffine }}) *{{ $TProjective }} { 1624 if a.X.IsZero() && a.Y.IsZero() { 1625 p.z.SetZero() 1626 p.x.SetOne() 1627 p.y.SetOne() 1628 return p 1629 } 1630 p.z.SetOne() 1631 p.x.Set(&a.X) 1632 p.y.Set(&a.Y) 1633 return p 1634 } 1635 1636 {{end }} 1637 1638 1639 {{/* note batch inversion for g2 elements with E2 that is curve specific is a bit more troublesome to implement */}} 1640 {{- if eq .PointName "g1"}} 1641 1642 // BatchJacobianToAffine{{ toUpper .PointName }} converts points in Jacobian coordinates to Affine coordinates 1643 // performing a single field inversion using the Montgomery batch inversion trick. 1644 func BatchJacobianToAffine{{ toUpper .PointName }}(points []{{ $TJacobian }}) []{{ $TAffine }} { 1645 result := make([]{{ $TAffine }}, len(points)) 1646 zeroes := make([]bool, len(points)) 1647 accumulator := fp.One() 1648 1649 // batch invert all points[].Z coordinates with Montgomery batch inversion trick 1650 // (stores points[].Z^-1 in result[i].X to avoid allocating a slice of fr.Elements) 1651 for i:=0; i < len(points); i++ { 1652 if points[i].Z.IsZero() { 1653 zeroes[i] = true 1654 continue 1655 } 1656 result[i].X = accumulator 1657 accumulator.Mul(&accumulator, &points[i].Z) 1658 } 1659 1660 var accInverse fp.Element 1661 accInverse.Inverse(&accumulator) 1662 1663 for i := len(points) - 1; i >= 0; i-- { 1664 if zeroes[i] { 1665 // do nothing, (X=0, Y=0) is infinity point in affine 1666 continue 1667 } 1668 result[i].X.Mul(&result[i].X, &accInverse) 1669 accInverse.Mul(&accInverse, &points[i].Z) 1670 } 1671 1672 // batch convert to affine. 1673 parallel.Execute( len(points), func(start, end int) { 1674 for i:=start; i < end; i++ { 1675 if zeroes[i] { 1676 // do nothing, (X=0, Y=0) is infinity point in affine 1677 continue 1678 } 1679 var a, b fp.Element 1680 a = result[i].X 1681 b.Square(&a) 1682 result[i].X.Mul(&points[i].X, &b) 1683 result[i].Y.Mul(&points[i].Y, &b). 1684 Mul(&result[i].Y, &a) 1685 } 1686 }) 1687 1688 return result 1689 } 1690 {{- end}} 1691 1692 1693 // BatchScalarMultiplication{{ toUpper .PointName }} multiplies the same base by all scalars 1694 // and return resulting points in affine coordinates 1695 // uses a simple windowed-NAF-like multiplication algorithm. 1696 func BatchScalarMultiplication{{ toUpper .PointName }}(base *{{ $TAffine }}, scalars []fr.Element) []{{ $TAffine }} { 1697 // approximate cost in group ops is 1698 // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) 1699 1700 nbPoints := uint64(len(scalars)) 1701 min := ^uint64(0) 1702 bestC := 0 1703 for c := 2; c <= 16; c++ { 1704 cost := uint64(1 << (c-1)) // pre compute the table 1705 nbChunks := computeNbChunks(uint64(c)) 1706 cost += nbPoints * (uint64(c) + 1) * nbChunks // doublings + point add 1707 if cost < min { 1708 min = cost 1709 bestC = c 1710 } 1711 } 1712 c := uint64(bestC) // window size 1713 nbChunks := int(computeNbChunks(c)) 1714 1715 // last window may be slightly larger than c; in which case we need to compute one 1716 // extra element in the baseTable 1717 maxC := lastC(c) 1718 if c > maxC { 1719 maxC = c 1720 } 1721 1722 // precompute all powers of base for our window 1723 // note here that if performance is critical, we can implement as in the msmX methods 1724 // this allocation to be on the stack 1725 baseTable := make([]{{ $TJacobian }}, (1<<(maxC-1))) 1726 baseTable[0].FromAffine(base) 1727 for i:=1;i<len(baseTable);i++ { 1728 baseTable[i] = baseTable[i-1] 1729 baseTable[i].AddMixed(base) 1730 } 1731 1732 {{- if eq .PointName "g1"}} 1733 // convert our base exp table into affine to use AddMixed 1734 baseTableAff := BatchJacobianToAffine{{ toUpper .PointName}}(baseTable) 1735 toReturn := make([]{{ $TJacobian }}, len(scalars)) 1736 {{- else}} 1737 toReturn := make([]{{ $TAffine }}, len(scalars)) 1738 {{- end}} 1739 1740 // partition the scalars into digits 1741 digits, _ := partitionScalars(scalars, c, runtime.NumCPU()) 1742 1743 // for each digit, take value in the base table, double it c time, voilà. 1744 parallel.Execute( len(scalars), func(start, end int) { 1745 var p {{ $TJacobian }} 1746 for i:=start; i < end; i++ { 1747 p.Set(&{{ toLower .PointName}}Infinity) 1748 for chunk := nbChunks - 1; chunk >=0; chunk-- { 1749 if chunk != nbChunks -1 { 1750 for j:=uint64(0); j<c; j++ { 1751 p.DoubleAssign() 1752 } 1753 } 1754 offset := chunk*len(scalars) 1755 digit := digits[i+offset] 1756 1757 if digit == 0 { 1758 continue 1759 } 1760 1761 // if msbWindow bit is set, we need to subtract 1762 if digit & 1 == 0 { 1763 // add 1764 {{- if eq .PointName "g1"}} 1765 p.AddMixed(&baseTableAff[(digit >> 1)-1]) 1766 {{- else}} 1767 p.AddAssign(&baseTable[(digit >> 1)-1]) 1768 {{- end}} 1769 } else { 1770 // sub 1771 {{- if eq .PointName "g1"}} 1772 t := baseTableAff[digit >> 1] 1773 t.Neg(&t) 1774 p.AddMixed(&t) 1775 {{- else}} 1776 t := baseTable[digit >> 1] 1777 t.Neg(&t) 1778 p.AddAssign(&t) 1779 {{- end}} 1780 } 1781 } 1782 1783 // set our result point 1784 {{- if eq .PointName "g1"}} 1785 toReturn[i] = p 1786 {{- else}} 1787 toReturn[i].FromJacobian(&p) 1788 {{- end}} 1789 1790 } 1791 }) 1792 1793 {{- if eq .PointName "g1"}} 1794 toReturnAff := BatchJacobianToAffine{{ toUpper .PointName}}(toReturn) 1795 return toReturnAff 1796 {{- else}} 1797 return toReturn 1798 {{- end}} 1799 } 1800 1801 // batchAdd{{ $TAffine }} adds affine points using the Montgomery batch inversion trick. 1802 // Special cases (doubling, infinity) must be filtered out before this call. 1803 func batchAdd{{ $TAffine }}[TP p{{ $TAffine }}, TPP pp{{ $TAffine }}, TC c{{ $TAffine }}](R *TPP,P *TP, batchSize int) { 1804 var lambda, lambdain TC 1805 1806 1807 // add part 1808 for j := 0; j < batchSize; j++ { 1809 lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) 1810 } 1811 1812 // invert denominator using montgomery batch invert technique 1813 { 1814 var accumulator {{.CoordType}} 1815 lambda[0].SetOne() 1816 accumulator.Set(&lambdain[0]) 1817 1818 for i := 1; i < batchSize; i++ { 1819 lambda[i] = accumulator 1820 accumulator.Mul(&accumulator, &lambdain[i]) 1821 } 1822 1823 accumulator.Inverse(&accumulator) 1824 1825 for i := batchSize - 1; i > 0; i-- { 1826 lambda[i].Mul(&lambda[i], &accumulator) 1827 accumulator.Mul(&accumulator, &lambdain[i]) 1828 } 1829 lambda[0].Set(&accumulator) 1830 } 1831 1832 var d {{.CoordType}} 1833 var rr {{ $TAffine }} 1834 1835 // add part 1836 for j := 0; j < batchSize; j++ { 1837 // computa lambda 1838 d.Sub(&(*P)[j].Y, &(*R)[j].Y) 1839 lambda[j].Mul(&lambda[j], &d) 1840 1841 // compute X, Y 1842 rr.X.Square(&lambda[j]) 1843 rr.X.Sub(&rr.X, &(*R)[j].X) 1844 rr.X.Sub(&rr.X, &(*P)[j].X) 1845 d.Sub(&(*R)[j].X, &rr.X) 1846 rr.Y.Mul(&lambda[j], &d) 1847 rr.Y.Sub(&rr.Y, &(*R)[j].Y) 1848 (*R)[j].Set(&rr) 1849 } 1850 } 1851 1852 {{ if eq .PointName "g2"}} 1853 // RandomOnG2 produces a random point in G2 1854 // using standard map-to-curve methods, which means the relative discrete log 1855 // of the generated point with respect to the canonical generator is not known. 1856 func RandomOnG2() (G2Affine, error) { 1857 if gBytes, err := randomFrSizedBytes(); err != nil { 1858 return G2Affine{}, err 1859 } else { 1860 return HashToG2(gBytes, []byte("random on g2")) 1861 } 1862 } 1863 1864 func randomFrSizedBytes() ([]byte, error) { 1865 res := make([]byte, fr.Bytes) 1866 _, err := rand.Read(res) 1867 return res, err 1868 } 1869 {{- end}}