github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-761/g1.go (about) 1 // Copyright 2020 Consensys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package bw6761 18 19 import ( 20 "github.com/consensys/gnark-crypto/ecc" 21 "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" 22 "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" 23 "github.com/consensys/gnark-crypto/internal/parallel" 24 "math/big" 25 "runtime" 26 ) 27 28 // G1Affine is a point in affine coordinates (x,y) 29 type G1Affine struct { 30 X, Y fp.Element 31 } 32 33 // G1Jac is a point in Jacobian coordinates (x=X/Z², y=Y/Z³) 34 type G1Jac struct { 35 X, Y, Z fp.Element 36 } 37 38 // g1JacExtended is a point in extended Jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ³=ZZZ²) 39 type g1JacExtended struct { 40 X, Y, ZZ, ZZZ fp.Element 41 } 42 43 // ------------------------------------------------------------------------------------------------- 44 // Affine coordinates 45 46 // Set sets p to a in affine coordinates. 47 func (p *G1Affine) Set(a *G1Affine) *G1Affine { 48 p.X, p.Y = a.X, a.Y 49 return p 50 } 51 52 // setInfinity sets p to the infinity point, which is encoded as (0,0). 53 // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). 54 func (p *G1Affine) setInfinity() *G1Affine { 55 p.X.SetZero() 56 p.Y.SetZero() 57 return p 58 } 59 60 // ScalarMultiplication computes and returns p = [s]a 61 // where p and a are affine points. 62 func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { 63 var _p G1Jac 64 _p.FromAffine(a) 65 _p.mulGLV(&_p, s) 66 p.FromJacobian(&_p) 67 return p 68 } 69 70 // ScalarMultiplicationBase computes and returns p = [s]g 71 // where g is the affine point generating the prime subgroup. 72 func (p *G1Affine) ScalarMultiplicationBase(s *big.Int) *G1Affine { 73 var _p G1Jac 74 _p.mulGLV(&g1Gen, s) 75 p.FromJacobian(&_p) 76 return p 77 } 78 79 // Add adds two points in affine coordinates. 80 // It uses the Jacobian addition with a.Z=b.Z=1 and converts the result to affine coordinates. 81 // 82 // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl 83 func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { 84 var q G1Jac 85 // a is infinity, return b 86 if a.IsInfinity() { 87 p.Set(b) 88 return p 89 } 90 // b is infinity, return a 91 if b.IsInfinity() { 92 p.Set(a) 93 return p 94 } 95 if a.X.Equal(&b.X) { 96 // if b == a, we double instead 97 if a.Y.Equal(&b.Y) { 98 q.DoubleMixed(a) 99 return p.FromJacobian(&q) 100 } else { 101 // if b == -a, we return 0 102 return p.setInfinity() 103 } 104 } 105 var H, HH, I, J, r, V fp.Element 106 H.Sub(&b.X, &a.X) 107 HH.Square(&H) 108 I.Double(&HH).Double(&I) 109 J.Mul(&H, &I) 110 r.Sub(&b.Y, &a.Y) 111 r.Double(&r) 112 V.Mul(&a.X, &I) 113 q.X.Square(&r). 114 Sub(&q.X, &J). 115 Sub(&q.X, &V). 116 Sub(&q.X, &V) 117 q.Y.Sub(&V, &q.X). 118 Mul(&q.Y, &r) 119 J.Mul(&a.Y, &J).Double(&J) 120 q.Y.Sub(&q.Y, &J) 121 q.Z.Double(&H) 122 123 return p.FromJacobian(&q) 124 } 125 126 // Double doubles a point in affine coordinates. 127 // It converts the point to Jacobian coordinates, doubles it using Jacobian 128 // addition with a.Z=1, and converts it back to affine coordinates. 129 // 130 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl 131 func (p *G1Affine) Double(a *G1Affine) *G1Affine { 132 var q G1Jac 133 q.FromAffine(a) 134 q.DoubleMixed(a) 135 p.FromJacobian(&q) 136 return p 137 } 138 139 // Sub subtracts two points in affine coordinates. 140 // It uses a similar approach to Add, but negates the second point before adding. 141 func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { 142 var bneg G1Affine 143 bneg.Neg(b) 144 p.Add(a, &bneg) 145 return p 146 } 147 148 // Equal tests if two points in affine coordinates are equal. 149 func (p *G1Affine) Equal(a *G1Affine) bool { 150 return p.X.Equal(&a.X) && p.Y.Equal(&a.Y) 151 } 152 153 // Neg sets p to the affine negative point -a = (a.X, -a.Y). 154 func (p *G1Affine) Neg(a *G1Affine) *G1Affine { 155 p.X = a.X 156 p.Y.Neg(&a.Y) 157 return p 158 } 159 160 // FromJacobian converts a point p1 from Jacobian to affine coordinates. 161 func (p *G1Affine) FromJacobian(p1 *G1Jac) *G1Affine { 162 163 var a, b fp.Element 164 165 if p1.Z.IsZero() { 166 p.X.SetZero() 167 p.Y.SetZero() 168 return p 169 } 170 171 a.Inverse(&p1.Z) 172 b.Square(&a) 173 p.X.Mul(&p1.X, &b) 174 p.Y.Mul(&p1.Y, &b).Mul(&p.Y, &a) 175 176 return p 177 } 178 179 // String returns the string representation E(x,y) of the affine point p or "O" if it is infinity. 180 func (p *G1Affine) String() string { 181 if p.IsInfinity() { 182 return "O" 183 } 184 return "E([" + p.X.String() + "," + p.Y.String() + "])" 185 } 186 187 // IsInfinity checks if the affine point p is infinity, which is encoded as (0,0). 188 // N.B.: (0,0) is never on the curve for j=0 curves (Y²=X³+B). 189 func (p *G1Affine) IsInfinity() bool { 190 return p.X.IsZero() && p.Y.IsZero() 191 } 192 193 // IsOnCurve returns true if the affine point p in on the curve. 194 func (p *G1Affine) IsOnCurve() bool { 195 var point G1Jac 196 point.FromAffine(p) 197 return point.IsOnCurve() // call this function to handle infinity point 198 } 199 200 // IsInSubGroup returns true if the affine point p is in the correct subgroup, false otherwise. 201 func (p *G1Affine) IsInSubGroup() bool { 202 var _p G1Jac 203 _p.FromAffine(p) 204 return _p.IsInSubGroup() 205 } 206 207 // ------------------------------------------------------------------------------------------------- 208 // Jacobian coordinates 209 210 // Set sets p to a in Jacobian coordinates. 211 func (p *G1Jac) Set(q *G1Jac) *G1Jac { 212 p.X, p.Y, p.Z = q.X, q.Y, q.Z 213 return p 214 } 215 216 // Equal tests if two points in Jacobian coordinates are equal. 217 func (p *G1Jac) Equal(q *G1Jac) bool { 218 // If one point is infinity, the other must also be infinity. 219 if p.Z.IsZero() { 220 return q.Z.IsZero() 221 } 222 // If the other point is infinity, return false since we can't 223 // the following checks would be incorrect. 224 if q.Z.IsZero() { 225 return false 226 } 227 228 var pZSquare, aZSquare fp.Element 229 pZSquare.Square(&p.Z) 230 aZSquare.Square(&q.Z) 231 232 var lhs, rhs fp.Element 233 lhs.Mul(&p.X, &aZSquare) 234 rhs.Mul(&q.X, &pZSquare) 235 if !lhs.Equal(&rhs) { 236 return false 237 } 238 lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &q.Z) 239 rhs.Mul(&q.Y, &pZSquare).Mul(&rhs, &p.Z) 240 241 return lhs.Equal(&rhs) 242 } 243 244 // Neg sets p to the Jacobian negative point -q = (q.X, -q.Y, q.Z). 245 func (p *G1Jac) Neg(q *G1Jac) *G1Jac { 246 *p = *q 247 p.Y.Neg(&q.Y) 248 return p 249 } 250 251 // AddAssign sets p to p+a in Jacobian coordinates. 252 // 253 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl 254 func (p *G1Jac) AddAssign(q *G1Jac) *G1Jac { 255 256 // p is infinity, return q 257 if p.Z.IsZero() { 258 p.Set(q) 259 return p 260 } 261 262 // q is infinity, return p 263 if q.Z.IsZero() { 264 return p 265 } 266 267 var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element 268 Z1Z1.Square(&q.Z) 269 Z2Z2.Square(&p.Z) 270 U1.Mul(&q.X, &Z2Z2) 271 U2.Mul(&p.X, &Z1Z1) 272 S1.Mul(&q.Y, &p.Z). 273 Mul(&S1, &Z2Z2) 274 S2.Mul(&p.Y, &q.Z). 275 Mul(&S2, &Z1Z1) 276 277 // if p == q, we double instead 278 if U1.Equal(&U2) && S1.Equal(&S2) { 279 return p.DoubleAssign() 280 } 281 282 H.Sub(&U2, &U1) 283 I.Double(&H). 284 Square(&I) 285 J.Mul(&H, &I) 286 r.Sub(&S2, &S1).Double(&r) 287 V.Mul(&U1, &I) 288 p.X.Square(&r). 289 Sub(&p.X, &J). 290 Sub(&p.X, &V). 291 Sub(&p.X, &V) 292 p.Y.Sub(&V, &p.X). 293 Mul(&p.Y, &r) 294 S1.Mul(&S1, &J).Double(&S1) 295 p.Y.Sub(&p.Y, &S1) 296 p.Z.Add(&p.Z, &q.Z) 297 p.Z.Square(&p.Z). 298 Sub(&p.Z, &Z1Z1). 299 Sub(&p.Z, &Z2Z2). 300 Mul(&p.Z, &H) 301 302 return p 303 } 304 305 // SubAssign sets p to p-a in Jacobian coordinates. 306 // It uses a similar approach to AddAssign, but negates the point a before adding. 307 func (p *G1Jac) SubAssign(q *G1Jac) *G1Jac { 308 var tmp G1Jac 309 tmp.Set(q) 310 tmp.Y.Neg(&tmp.Y) 311 p.AddAssign(&tmp) 312 return p 313 } 314 315 // Double sets p to [2]q in Jacobian coordinates. 316 // 317 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 318 func (p *G1Jac) DoubleMixed(a *G1Affine) *G1Jac { 319 var XX, YY, YYYY, S, M, T fp.Element 320 XX.Square(&a.X) 321 YY.Square(&a.Y) 322 YYYY.Square(&YY) 323 S.Add(&a.X, &YY). 324 Square(&S). 325 Sub(&S, &XX). 326 Sub(&S, &YYYY). 327 Double(&S) 328 M.Double(&XX). 329 Add(&M, &XX) // -> + A, but A=0 here 330 T.Square(&M). 331 Sub(&T, &S). 332 Sub(&T, &S) 333 p.X.Set(&T) 334 p.Y.Sub(&S, &T). 335 Mul(&p.Y, &M) 336 YYYY.Double(&YYYY). 337 Double(&YYYY). 338 Double(&YYYY) 339 p.Y.Sub(&p.Y, &YYYY) 340 p.Z.Double(&a.Y) 341 342 return p 343 } 344 345 // AddMixed sets p to p+a in Jacobian coordinates, where a.Z = 1. 346 // 347 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl 348 func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { 349 350 //if a is infinity return p 351 if a.IsInfinity() { 352 return p 353 } 354 // p is infinity, return a 355 if p.Z.IsZero() { 356 p.X = a.X 357 p.Y = a.Y 358 p.Z.SetOne() 359 return p 360 } 361 362 var Z1Z1, U2, S2, H, HH, I, J, r, V fp.Element 363 Z1Z1.Square(&p.Z) 364 U2.Mul(&a.X, &Z1Z1) 365 S2.Mul(&a.Y, &p.Z). 366 Mul(&S2, &Z1Z1) 367 368 // if p == a, we double instead 369 if U2.Equal(&p.X) && S2.Equal(&p.Y) { 370 return p.DoubleMixed(a) 371 } 372 373 H.Sub(&U2, &p.X) 374 HH.Square(&H) 375 I.Double(&HH).Double(&I) 376 J.Mul(&H, &I) 377 r.Sub(&S2, &p.Y).Double(&r) 378 V.Mul(&p.X, &I) 379 p.X.Square(&r). 380 Sub(&p.X, &J). 381 Sub(&p.X, &V). 382 Sub(&p.X, &V) 383 J.Mul(&J, &p.Y).Double(&J) 384 p.Y.Sub(&V, &p.X). 385 Mul(&p.Y, &r) 386 p.Y.Sub(&p.Y, &J) 387 p.Z.Add(&p.Z, &H) 388 p.Z.Square(&p.Z). 389 Sub(&p.Z, &Z1Z1). 390 Sub(&p.Z, &HH) 391 392 return p 393 } 394 395 // Double sets p to [2]q in Jacobian coordinates. 396 // 397 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 398 func (p *G1Jac) Double(q *G1Jac) *G1Jac { 399 p.Set(q) 400 p.DoubleAssign() 401 return p 402 } 403 404 // DoubleAssign doubles p in Jacobian coordinates. 405 // 406 // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl 407 func (p *G1Jac) DoubleAssign() *G1Jac { 408 409 var XX, YY, YYYY, ZZ, S, M, T fp.Element 410 411 XX.Square(&p.X) 412 YY.Square(&p.Y) 413 YYYY.Square(&YY) 414 ZZ.Square(&p.Z) 415 S.Add(&p.X, &YY) 416 S.Square(&S). 417 Sub(&S, &XX). 418 Sub(&S, &YYYY). 419 Double(&S) 420 M.Double(&XX).Add(&M, &XX) 421 p.Z.Add(&p.Z, &p.Y). 422 Square(&p.Z). 423 Sub(&p.Z, &YY). 424 Sub(&p.Z, &ZZ) 425 T.Square(&M) 426 p.X = T 427 T.Double(&S) 428 p.X.Sub(&p.X, &T) 429 p.Y.Sub(&S, &p.X). 430 Mul(&p.Y, &M) 431 YYYY.Double(&YYYY).Double(&YYYY).Double(&YYYY) 432 p.Y.Sub(&p.Y, &YYYY) 433 434 return p 435 } 436 437 // ScalarMultiplication computes and returns p = [s]a 438 // where p and a are Jacobian points. 439 // using the GLV technique. 440 // see https://www.iacr.org/archive/crypto2001/21390189.pdf 441 func (p *G1Jac) ScalarMultiplication(q *G1Jac, s *big.Int) *G1Jac { 442 return p.mulGLV(q, s) 443 } 444 445 // ScalarMultiplicationBase computes and returns p = [s]g 446 // where g is the prime subgroup generator. 447 func (p *G1Jac) ScalarMultiplicationBase(s *big.Int) *G1Jac { 448 return p.mulGLV(&g1Gen, s) 449 450 } 451 452 // String converts p to affine coordinates and returns its string representation E(x,y) or "O" if it is infinity. 453 func (p *G1Jac) String() string { 454 _p := G1Affine{} 455 _p.FromJacobian(p) 456 return _p.String() 457 } 458 459 // FromAffine converts a point a from affine to Jacobian coordinates. 460 func (p *G1Jac) FromAffine(a *G1Affine) *G1Jac { 461 if a.IsInfinity() { 462 p.Z.SetZero() 463 p.X.SetOne() 464 p.Y.SetOne() 465 return p 466 } 467 p.Z.SetOne() 468 p.X.Set(&a.X) 469 p.Y.Set(&a.Y) 470 return p 471 } 472 473 // IsOnCurve returns true if the Jacobian point p in on the curve. 474 func (p *G1Jac) IsOnCurve() bool { 475 var left, right, tmp, ZZ fp.Element 476 left.Square(&p.Y) 477 right.Square(&p.X).Mul(&right, &p.X) 478 ZZ.Square(&p.Z) 479 tmp.Square(&ZZ).Mul(&tmp, &ZZ) 480 // Mul tmp by bCurveCoeff=-1 481 tmp.Neg(&tmp) 482 right.Add(&right, &tmp) 483 return left.Equal(&right) 484 } 485 486 // IsInSubGroup returns true if p is on the r-torsion, false otherwise. 487 488 // Z[r,0]+Z[-lambdaG1Affine, 1] is the kernel 489 // of (u,v)->u+lambdaG1Affinev mod r. Expressing r, lambdaG1Affine as 490 // polynomials in x, a short vector of this Zmodule is 491 // (x+1), (x³-x²+1). So we check that (x+1)p+(x³-x²+1)ϕ(p) 492 // is the infinity. 493 func (p *G1Jac) IsInSubGroup() bool { 494 495 var res, phip G1Jac 496 phip.phi(p) 497 res.ScalarMultiplication(&phip, &xGen). 498 SubAssign(&phip). 499 ScalarMultiplication(&res, &xGen). 500 ScalarMultiplication(&res, &xGen). 501 AddAssign(&phip) 502 503 phip.ScalarMultiplication(p, &xGen).AddAssign(p).AddAssign(&res) 504 505 return phip.IsOnCurve() && phip.Z.IsZero() 506 507 } 508 509 // mulWindowed computes the 2-bits windowed double-and-add scalar 510 // multiplication p=[s]q in Jacobian coordinates. 511 func (p *G1Jac) mulWindowed(q *G1Jac, s *big.Int) *G1Jac { 512 513 var res G1Jac 514 var ops [3]G1Jac 515 516 ops[0].Set(q) 517 if s.Sign() == -1 { 518 ops[0].Neg(&ops[0]) 519 } 520 res.Set(&g1Infinity) 521 ops[1].Double(&ops[0]) 522 ops[2].Set(&ops[0]).AddAssign(&ops[1]) 523 524 b := s.Bytes() 525 for i := range b { 526 w := b[i] 527 mask := byte(0xc0) 528 for j := 0; j < 4; j++ { 529 res.DoubleAssign().DoubleAssign() 530 c := (w & mask) >> (6 - 2*j) 531 if c != 0 { 532 res.AddAssign(&ops[c-1]) 533 } 534 mask = mask >> 2 535 } 536 } 537 p.Set(&res) 538 539 return p 540 541 } 542 543 // phi sets p to ϕ(a) where ϕ: (x,y) → (w x,y), 544 // where w is a third root of unity. 545 func (p *G1Jac) phi(q *G1Jac) *G1Jac { 546 p.Set(q) 547 p.X.Mul(&p.X, &thirdRootOneG1) 548 return p 549 } 550 551 // mulGLV computes the scalar multiplication using a windowed-GLV method 552 // 553 // see https://www.iacr.org/archive/crypto2001/21390189.pdf 554 func (p *G1Jac) mulGLV(q *G1Jac, s *big.Int) *G1Jac { 555 556 var table [15]G1Jac 557 var res G1Jac 558 var k1, k2 fr.Element 559 560 res.Set(&g1Infinity) 561 562 // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0*q 563 table[0].Set(q) 564 table[3].phi(q) 565 566 // split the scalar, modifies ±q, ϕ(q) accordingly 567 k := ecc.SplitScalar(s, &glvBasis) 568 569 if k[0].Sign() == -1 { 570 k[0].Neg(&k[0]) 571 table[0].Neg(&table[0]) 572 } 573 if k[1].Sign() == -1 { 574 k[1].Neg(&k[1]) 575 table[3].Neg(&table[3]) 576 } 577 578 // precompute table (2 bits sliding window) 579 // table[b3b2b1b0-1] = b3b2 ⋅ ϕ(q) + b1b0 ⋅ q if b3b2b1b0 != 0 580 table[1].Double(&table[0]) 581 table[2].Set(&table[1]).AddAssign(&table[0]) 582 table[4].Set(&table[3]).AddAssign(&table[0]) 583 table[5].Set(&table[3]).AddAssign(&table[1]) 584 table[6].Set(&table[3]).AddAssign(&table[2]) 585 table[7].Double(&table[3]) 586 table[8].Set(&table[7]).AddAssign(&table[0]) 587 table[9].Set(&table[7]).AddAssign(&table[1]) 588 table[10].Set(&table[7]).AddAssign(&table[2]) 589 table[11].Set(&table[7]).AddAssign(&table[3]) 590 table[12].Set(&table[11]).AddAssign(&table[0]) 591 table[13].Set(&table[11]).AddAssign(&table[1]) 592 table[14].Set(&table[11]).AddAssign(&table[2]) 593 594 // bounds on the lattice base vectors guarantee that k1, k2 are len(r)/2 or len(r)/2+1 bits long max 595 // this is because we use a probabilistic scalar decomposition that replaces a division by a right-shift 596 k1 = k1.SetBigInt(&k[0]).Bits() 597 k2 = k2.SetBigInt(&k[1]).Bits() 598 599 // we don't target constant-timeness so we check first if we increase the bounds or not 600 maxBit := k1.BitLen() 601 if k2.BitLen() > maxBit { 602 maxBit = k2.BitLen() 603 } 604 hiWordIndex := (maxBit - 1) / 64 605 606 // loop starts from len(k1)/2 or len(k1)/2+1 due to the bounds 607 for i := hiWordIndex; i >= 0; i-- { 608 mask := uint64(3) << 62 609 for j := 0; j < 32; j++ { 610 res.Double(&res).Double(&res) 611 b1 := (k1[i] & mask) >> (62 - 2*j) 612 b2 := (k2[i] & mask) >> (62 - 2*j) 613 if b1|b2 != 0 { 614 s := (b2<<2 | b1) 615 res.AddAssign(&table[s-1]) 616 } 617 mask = mask >> 2 618 } 619 } 620 621 p.Set(&res) 622 return p 623 } 624 625 // ClearCofactor maps a point in curve to r-torsion 626 func (p *G1Affine) ClearCofactor(a *G1Affine) *G1Affine { 627 var _p G1Jac 628 _p.FromAffine(a) 629 _p.ClearCofactor(&_p) 630 p.FromJacobian(&_p) 631 return p 632 } 633 634 // ClearCofactor maps a point in E(Fp) to E(Fp)[r] 635 func (p *G1Jac) ClearCofactor(q *G1Jac) *G1Jac { 636 637 // https://eprint.iacr.org/2020/351.pdf 638 var points [4]G1Jac 639 points[0].Set(q) 640 points[1].ScalarMultiplication(q, &xGen) 641 points[2].ScalarMultiplication(&points[1], &xGen) 642 points[3].ScalarMultiplication(&points[2], &xGen) 643 644 var scalars [7]big.Int 645 scalars[0].SetInt64(103) 646 scalars[1].SetInt64(83) 647 scalars[2].SetInt64(40) 648 scalars[3].SetInt64(136) 649 650 scalars[4].SetInt64(7) 651 scalars[5].SetInt64(89) 652 scalars[6].SetInt64(130) 653 654 var p1, p2, tmp G1Jac 655 p1.ScalarMultiplication(&points[3], &scalars[0]) 656 tmp.ScalarMultiplication(&points[2], &scalars[1]).Neg(&tmp) 657 p1.AddAssign(&tmp) 658 tmp.ScalarMultiplication(&points[1], &scalars[2]).Neg(&tmp) 659 p1.AddAssign(&tmp) 660 tmp.ScalarMultiplication(&points[0], &scalars[3]) 661 p1.AddAssign(&tmp) 662 663 p2.ScalarMultiplication(&points[2], &scalars[4]) 664 tmp.ScalarMultiplication(&points[1], &scalars[5]) 665 p2.AddAssign(&tmp) 666 tmp.ScalarMultiplication(&points[0], &scalars[6]) 667 p2.AddAssign(&tmp) 668 p2.phi(&p2) 669 670 p.Set(&p1).AddAssign(&p2) 671 672 return p 673 674 } 675 676 // JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique 677 // where a1 and a2 are affine points. 678 func (p *G1Jac) JointScalarMultiplication(a1, a2 *G1Affine, s1, s2 *big.Int) *G1Jac { 679 680 var res, p1, p2 G1Jac 681 res.Set(&g1Infinity) 682 p1.FromAffine(a1) 683 p2.FromAffine(a2) 684 685 var table [15]G1Jac 686 687 var k1, k2 big.Int 688 if s1.Sign() == -1 { 689 k1.Neg(s1) 690 table[0].Neg(&p1) 691 } else { 692 k1.Set(s1) 693 table[0].Set(&p1) 694 } 695 if s2.Sign() == -1 { 696 k2.Neg(s2) 697 table[3].Neg(&p2) 698 } else { 699 k2.Set(s2) 700 table[3].Set(&p2) 701 } 702 703 // precompute table (2 bits sliding window) 704 table[1].Double(&table[0]) 705 table[2].Set(&table[1]).AddAssign(&table[0]) 706 table[4].Set(&table[3]).AddAssign(&table[0]) 707 table[5].Set(&table[3]).AddAssign(&table[1]) 708 table[6].Set(&table[3]).AddAssign(&table[2]) 709 table[7].Double(&table[3]) 710 table[8].Set(&table[7]).AddAssign(&table[0]) 711 table[9].Set(&table[7]).AddAssign(&table[1]) 712 table[10].Set(&table[7]).AddAssign(&table[2]) 713 table[11].Set(&table[7]).AddAssign(&table[3]) 714 table[12].Set(&table[11]).AddAssign(&table[0]) 715 table[13].Set(&table[11]).AddAssign(&table[1]) 716 table[14].Set(&table[11]).AddAssign(&table[2]) 717 718 var s [2]fr.Element 719 s[0] = s[0].SetBigInt(&k1).Bits() 720 s[1] = s[1].SetBigInt(&k2).Bits() 721 722 maxBit := k1.BitLen() 723 if k2.BitLen() > maxBit { 724 maxBit = k2.BitLen() 725 } 726 hiWordIndex := (maxBit - 1) / 64 727 728 for i := hiWordIndex; i >= 0; i-- { 729 mask := uint64(3) << 62 730 for j := 0; j < 32; j++ { 731 res.Double(&res).Double(&res) 732 b1 := (s[0][i] & mask) >> (62 - 2*j) 733 b2 := (s[1][i] & mask) >> (62 - 2*j) 734 if b1|b2 != 0 { 735 s := (b2<<2 | b1) 736 res.AddAssign(&table[s-1]) 737 } 738 mask = mask >> 2 739 } 740 } 741 742 p.Set(&res) 743 return p 744 745 } 746 747 // JointScalarMultiplicationBase computes [s1]g+[s2]a using Straus-Shamir technique 748 // where g is the prime subgroup generator. 749 func (p *G1Jac) JointScalarMultiplicationBase(a *G1Affine, s1, s2 *big.Int) *G1Jac { 750 return p.JointScalarMultiplication(&g1GenAff, a, s1, s2) 751 752 } 753 754 // ------------------------------------------------------------------------------------------------- 755 // extended Jacobian coordinates 756 757 // Set sets p to a in extended Jacobian coordinates. 758 func (p *g1JacExtended) Set(q *g1JacExtended) *g1JacExtended { 759 p.X, p.Y, p.ZZ, p.ZZZ = q.X, q.Y, q.ZZ, q.ZZZ 760 return p 761 } 762 763 // setInfinity sets p to the infinity point (1,1,0,0). 764 func (p *g1JacExtended) setInfinity() *g1JacExtended { 765 p.X.SetOne() 766 p.Y.SetOne() 767 p.ZZ = fp.Element{} 768 p.ZZZ = fp.Element{} 769 return p 770 } 771 772 // IsInfinity checks if the p is infinity, i.e. p.ZZ=0. 773 func (p *g1JacExtended) IsInfinity() bool { 774 return p.ZZ.IsZero() 775 } 776 777 // fromJacExtended converts an extended Jacobian point to an affine point. 778 func (p *G1Affine) fromJacExtended(q *g1JacExtended) *G1Affine { 779 if q.ZZ.IsZero() { 780 p.X = fp.Element{} 781 p.Y = fp.Element{} 782 return p 783 } 784 p.X.Inverse(&q.ZZ).Mul(&p.X, &q.X) 785 p.Y.Inverse(&q.ZZZ).Mul(&p.Y, &q.Y) 786 return p 787 } 788 789 // fromJacExtended converts an extended Jacobian point to a Jacobian point. 790 func (p *G1Jac) fromJacExtended(q *g1JacExtended) *G1Jac { 791 if q.ZZ.IsZero() { 792 p.Set(&g1Infinity) 793 return p 794 } 795 p.X.Mul(&q.ZZ, &q.X).Mul(&p.X, &q.ZZ) 796 p.Y.Mul(&q.ZZZ, &q.Y).Mul(&p.Y, &q.ZZZ) 797 p.Z.Set(&q.ZZZ) 798 return p 799 } 800 801 // unsafeFromJacExtended converts an extended Jacobian point, distinct from Infinity, to a Jacobian point. 802 func (p *G1Jac) unsafeFromJacExtended(q *g1JacExtended) *G1Jac { 803 p.X.Square(&q.ZZ).Mul(&p.X, &q.X) 804 p.Y.Square(&q.ZZZ).Mul(&p.Y, &q.Y) 805 p.Z = q.ZZZ 806 return p 807 } 808 809 // add sets p to p+q in extended Jacobian coordinates. 810 // 811 // https://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-add-2008-s 812 func (p *g1JacExtended) add(q *g1JacExtended) *g1JacExtended { 813 //if q is infinity return p 814 if q.ZZ.IsZero() { 815 return p 816 } 817 // p is infinity, return q 818 if p.ZZ.IsZero() { 819 p.Set(q) 820 return p 821 } 822 823 var A, B, U1, U2, S1, S2 fp.Element 824 825 // p2: q, p1: p 826 U2.Mul(&q.X, &p.ZZ) 827 U1.Mul(&p.X, &q.ZZ) 828 A.Sub(&U2, &U1) 829 S2.Mul(&q.Y, &p.ZZZ) 830 S1.Mul(&p.Y, &q.ZZZ) 831 B.Sub(&S2, &S1) 832 833 if A.IsZero() { 834 if B.IsZero() { 835 return p.double(q) 836 837 } 838 p.ZZ = fp.Element{} 839 p.ZZZ = fp.Element{} 840 return p 841 } 842 843 var P, R, PP, PPP, Q, V fp.Element 844 P.Sub(&U2, &U1) 845 R.Sub(&S2, &S1) 846 PP.Square(&P) 847 PPP.Mul(&P, &PP) 848 Q.Mul(&U1, &PP) 849 V.Mul(&S1, &PPP) 850 851 p.X.Square(&R). 852 Sub(&p.X, &PPP). 853 Sub(&p.X, &Q). 854 Sub(&p.X, &Q) 855 p.Y.Sub(&Q, &p.X). 856 Mul(&p.Y, &R). 857 Sub(&p.Y, &V) 858 p.ZZ.Mul(&p.ZZ, &q.ZZ). 859 Mul(&p.ZZ, &PP) 860 p.ZZZ.Mul(&p.ZZZ, &q.ZZZ). 861 Mul(&p.ZZZ, &PPP) 862 863 return p 864 } 865 866 // double sets p to [2]q in Jacobian extended coordinates. 867 // 868 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 869 // N.B.: since we consider any point on Z=0 as the point at infinity 870 // this doubling formula works for infinity points as well. 871 func (p *g1JacExtended) double(q *g1JacExtended) *g1JacExtended { 872 var U, V, W, S, XX, M fp.Element 873 874 U.Double(&q.Y) 875 V.Square(&U) 876 W.Mul(&U, &V) 877 S.Mul(&q.X, &V) 878 XX.Square(&q.X) 879 M.Double(&XX). 880 Add(&M, &XX) // -> + A, but A=0 here 881 U.Mul(&W, &q.Y) 882 883 p.X.Square(&M). 884 Sub(&p.X, &S). 885 Sub(&p.X, &S) 886 p.Y.Sub(&S, &p.X). 887 Mul(&p.Y, &M). 888 Sub(&p.Y, &U) 889 p.ZZ.Mul(&V, &q.ZZ) 890 p.ZZZ.Mul(&W, &q.ZZZ) 891 892 return p 893 } 894 895 // addMixed sets p to p+q in extended Jacobian coordinates, where a.ZZ=1. 896 // 897 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s 898 func (p *g1JacExtended) addMixed(a *G1Affine) *g1JacExtended { 899 900 //if a is infinity return p 901 if a.IsInfinity() { 902 return p 903 } 904 // p is infinity, return a 905 if p.ZZ.IsZero() { 906 p.X = a.X 907 p.Y = a.Y 908 p.ZZ.SetOne() 909 p.ZZZ.SetOne() 910 return p 911 } 912 913 var P, R fp.Element 914 915 // p2: a, p1: p 916 P.Mul(&a.X, &p.ZZ) 917 P.Sub(&P, &p.X) 918 919 R.Mul(&a.Y, &p.ZZZ) 920 R.Sub(&R, &p.Y) 921 922 if P.IsZero() { 923 if R.IsZero() { 924 return p.doubleMixed(a) 925 926 } 927 p.ZZ = fp.Element{} 928 p.ZZZ = fp.Element{} 929 return p 930 } 931 932 var PP, PPP, Q, Q2, RR, X3, Y3 fp.Element 933 934 PP.Square(&P) 935 PPP.Mul(&P, &PP) 936 Q.Mul(&p.X, &PP) 937 RR.Square(&R) 938 X3.Sub(&RR, &PPP) 939 Q2.Double(&Q) 940 p.X.Sub(&X3, &Q2) 941 Y3.Sub(&Q, &p.X).Mul(&Y3, &R) 942 R.Mul(&p.Y, &PPP) 943 p.Y.Sub(&Y3, &R) 944 p.ZZ.Mul(&p.ZZ, &PP) 945 p.ZZZ.Mul(&p.ZZZ, &PPP) 946 947 return p 948 949 } 950 951 // subMixed works the same as addMixed, but negates a.Y. 952 // 953 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#addition-madd-2008-s 954 func (p *g1JacExtended) subMixed(a *G1Affine) *g1JacExtended { 955 956 //if a is infinity return p 957 if a.IsInfinity() { 958 return p 959 } 960 // p is infinity, return a 961 if p.ZZ.IsZero() { 962 p.X = a.X 963 p.Y.Neg(&a.Y) 964 p.ZZ.SetOne() 965 p.ZZZ.SetOne() 966 return p 967 } 968 969 var P, R fp.Element 970 971 // p2: a, p1: p 972 P.Mul(&a.X, &p.ZZ) 973 P.Sub(&P, &p.X) 974 975 R.Mul(&a.Y, &p.ZZZ) 976 R.Neg(&R) 977 R.Sub(&R, &p.Y) 978 979 if P.IsZero() { 980 if R.IsZero() { 981 return p.doubleNegMixed(a) 982 983 } 984 p.ZZ = fp.Element{} 985 p.ZZZ = fp.Element{} 986 return p 987 } 988 989 var PP, PPP, Q, Q2, RR, X3, Y3 fp.Element 990 991 PP.Square(&P) 992 PPP.Mul(&P, &PP) 993 Q.Mul(&p.X, &PP) 994 RR.Square(&R) 995 X3.Sub(&RR, &PPP) 996 Q2.Double(&Q) 997 p.X.Sub(&X3, &Q2) 998 Y3.Sub(&Q, &p.X).Mul(&Y3, &R) 999 R.Mul(&p.Y, &PPP) 1000 p.Y.Sub(&Y3, &R) 1001 p.ZZ.Mul(&p.ZZ, &PP) 1002 p.ZZZ.Mul(&p.ZZZ, &PPP) 1003 1004 return p 1005 1006 } 1007 1008 // doubleNegMixed works the same as double, but negates q.Y. 1009 func (p *g1JacExtended) doubleNegMixed(a *G1Affine) *g1JacExtended { 1010 1011 var U, V, W, S, XX, M, S2, L fp.Element 1012 1013 U.Double(&a.Y) 1014 U.Neg(&U) 1015 V.Square(&U) 1016 W.Mul(&U, &V) 1017 S.Mul(&a.X, &V) 1018 XX.Square(&a.X) 1019 M.Double(&XX). 1020 Add(&M, &XX) // -> + A, but A=0 here 1021 S2.Double(&S) 1022 L.Mul(&W, &a.Y) 1023 1024 p.X.Square(&M). 1025 Sub(&p.X, &S2) 1026 p.Y.Sub(&S, &p.X). 1027 Mul(&p.Y, &M). 1028 Add(&p.Y, &L) 1029 p.ZZ.Set(&V) 1030 p.ZZZ.Set(&W) 1031 1032 return p 1033 } 1034 1035 // doubleMixed sets p to [2]a in Jacobian extended coordinates, where a.ZZ=1. 1036 // 1037 // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 1038 func (p *g1JacExtended) doubleMixed(a *G1Affine) *g1JacExtended { 1039 1040 var U, V, W, S, XX, M, S2, L fp.Element 1041 1042 U.Double(&a.Y) 1043 V.Square(&U) 1044 W.Mul(&U, &V) 1045 S.Mul(&a.X, &V) 1046 XX.Square(&a.X) 1047 M.Double(&XX). 1048 Add(&M, &XX) // -> + A, but A=0 here 1049 S2.Double(&S) 1050 L.Mul(&W, &a.Y) 1051 1052 p.X.Square(&M). 1053 Sub(&p.X, &S2) 1054 p.Y.Sub(&S, &p.X). 1055 Mul(&p.Y, &M). 1056 Sub(&p.Y, &L) 1057 p.ZZ.Set(&V) 1058 p.ZZZ.Set(&W) 1059 1060 return p 1061 } 1062 1063 // BatchJacobianToAffineG1 converts points in Jacobian coordinates to Affine coordinates 1064 // performing a single field inversion using the Montgomery batch inversion trick. 1065 func BatchJacobianToAffineG1(points []G1Jac) []G1Affine { 1066 result := make([]G1Affine, len(points)) 1067 zeroes := make([]bool, len(points)) 1068 accumulator := fp.One() 1069 1070 // batch invert all points[].Z coordinates with Montgomery batch inversion trick 1071 // (stores points[].Z^-1 in result[i].X to avoid allocating a slice of fr.Elements) 1072 for i := 0; i < len(points); i++ { 1073 if points[i].Z.IsZero() { 1074 zeroes[i] = true 1075 continue 1076 } 1077 result[i].X = accumulator 1078 accumulator.Mul(&accumulator, &points[i].Z) 1079 } 1080 1081 var accInverse fp.Element 1082 accInverse.Inverse(&accumulator) 1083 1084 for i := len(points) - 1; i >= 0; i-- { 1085 if zeroes[i] { 1086 // do nothing, (X=0, Y=0) is infinity point in affine 1087 continue 1088 } 1089 result[i].X.Mul(&result[i].X, &accInverse) 1090 accInverse.Mul(&accInverse, &points[i].Z) 1091 } 1092 1093 // batch convert to affine. 1094 parallel.Execute(len(points), func(start, end int) { 1095 for i := start; i < end; i++ { 1096 if zeroes[i] { 1097 // do nothing, (X=0, Y=0) is infinity point in affine 1098 continue 1099 } 1100 var a, b fp.Element 1101 a = result[i].X 1102 b.Square(&a) 1103 result[i].X.Mul(&points[i].X, &b) 1104 result[i].Y.Mul(&points[i].Y, &b). 1105 Mul(&result[i].Y, &a) 1106 } 1107 }) 1108 1109 return result 1110 } 1111 1112 // BatchScalarMultiplicationG1 multiplies the same base by all scalars 1113 // and return resulting points in affine coordinates 1114 // uses a simple windowed-NAF-like multiplication algorithm. 1115 func BatchScalarMultiplicationG1(base *G1Affine, scalars []fr.Element) []G1Affine { 1116 // approximate cost in group ops is 1117 // cost = 2^{c-1} + n(scalar.nbBits+nbChunks) 1118 1119 nbPoints := uint64(len(scalars)) 1120 min := ^uint64(0) 1121 bestC := 0 1122 for c := 2; c <= 16; c++ { 1123 cost := uint64(1 << (c - 1)) // pre compute the table 1124 nbChunks := computeNbChunks(uint64(c)) 1125 cost += nbPoints * (uint64(c) + 1) * nbChunks // doublings + point add 1126 if cost < min { 1127 min = cost 1128 bestC = c 1129 } 1130 } 1131 c := uint64(bestC) // window size 1132 nbChunks := int(computeNbChunks(c)) 1133 1134 // last window may be slightly larger than c; in which case we need to compute one 1135 // extra element in the baseTable 1136 maxC := lastC(c) 1137 if c > maxC { 1138 maxC = c 1139 } 1140 1141 // precompute all powers of base for our window 1142 // note here that if performance is critical, we can implement as in the msmX methods 1143 // this allocation to be on the stack 1144 baseTable := make([]G1Jac, (1 << (maxC - 1))) 1145 baseTable[0].FromAffine(base) 1146 for i := 1; i < len(baseTable); i++ { 1147 baseTable[i] = baseTable[i-1] 1148 baseTable[i].AddMixed(base) 1149 } 1150 // convert our base exp table into affine to use AddMixed 1151 baseTableAff := BatchJacobianToAffineG1(baseTable) 1152 toReturn := make([]G1Jac, len(scalars)) 1153 1154 // partition the scalars into digits 1155 digits, _ := partitionScalars(scalars, c, runtime.NumCPU()) 1156 1157 // for each digit, take value in the base table, double it c time, voilà. 1158 parallel.Execute(len(scalars), func(start, end int) { 1159 var p G1Jac 1160 for i := start; i < end; i++ { 1161 p.Set(&g1Infinity) 1162 for chunk := nbChunks - 1; chunk >= 0; chunk-- { 1163 if chunk != nbChunks-1 { 1164 for j := uint64(0); j < c; j++ { 1165 p.DoubleAssign() 1166 } 1167 } 1168 offset := chunk * len(scalars) 1169 digit := digits[i+offset] 1170 1171 if digit == 0 { 1172 continue 1173 } 1174 1175 // if msbWindow bit is set, we need to subtract 1176 if digit&1 == 0 { 1177 // add 1178 p.AddMixed(&baseTableAff[(digit>>1)-1]) 1179 } else { 1180 // sub 1181 t := baseTableAff[digit>>1] 1182 t.Neg(&t) 1183 p.AddMixed(&t) 1184 } 1185 } 1186 1187 // set our result point 1188 toReturn[i] = p 1189 1190 } 1191 }) 1192 toReturnAff := BatchJacobianToAffineG1(toReturn) 1193 return toReturnAff 1194 } 1195 1196 // batchAddG1Affine adds affine points using the Montgomery batch inversion trick. 1197 // Special cases (doubling, infinity) must be filtered out before this call. 1198 func batchAddG1Affine[TP pG1Affine, TPP ppG1Affine, TC cG1Affine](R *TPP, P *TP, batchSize int) { 1199 var lambda, lambdain TC 1200 1201 // add part 1202 for j := 0; j < batchSize; j++ { 1203 lambdain[j].Sub(&(*P)[j].X, &(*R)[j].X) 1204 } 1205 1206 // invert denominator using montgomery batch invert technique 1207 { 1208 var accumulator fp.Element 1209 lambda[0].SetOne() 1210 accumulator.Set(&lambdain[0]) 1211 1212 for i := 1; i < batchSize; i++ { 1213 lambda[i] = accumulator 1214 accumulator.Mul(&accumulator, &lambdain[i]) 1215 } 1216 1217 accumulator.Inverse(&accumulator) 1218 1219 for i := batchSize - 1; i > 0; i-- { 1220 lambda[i].Mul(&lambda[i], &accumulator) 1221 accumulator.Mul(&accumulator, &lambdain[i]) 1222 } 1223 lambda[0].Set(&accumulator) 1224 } 1225 1226 var d fp.Element 1227 var rr G1Affine 1228 1229 // add part 1230 for j := 0; j < batchSize; j++ { 1231 // computa lambda 1232 d.Sub(&(*P)[j].Y, &(*R)[j].Y) 1233 lambda[j].Mul(&lambda[j], &d) 1234 1235 // compute X, Y 1236 rr.X.Square(&lambda[j]) 1237 rr.X.Sub(&rr.X, &(*R)[j].X) 1238 rr.X.Sub(&rr.X, &(*P)[j].X) 1239 d.Sub(&(*R)[j].X, &rr.X) 1240 rr.Y.Mul(&lambda[j], &d) 1241 rr.Y.Sub(&rr.Y, &(*R)[j].Y) 1242 (*R)[j].Set(&rr) 1243 } 1244 }