github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-761/twistededwards/point.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 twistededwards
    18  
    19  import (
    20  	"crypto/subtle"
    21  	"io"
    22  	"math/big"
    23  	"math/bits"
    24  
    25  	"github.com/consensys/gnark-crypto/ecc/bw6-761/fr"
    26  )
    27  
    28  // PointAffine point on a twisted Edwards curve
    29  type PointAffine struct {
    30  	X, Y fr.Element
    31  }
    32  
    33  // PointProj point in projective coordinates
    34  type PointProj struct {
    35  	X, Y, Z fr.Element
    36  }
    37  
    38  // PointExtended point in extended coordinates
    39  type PointExtended struct {
    40  	X, Y, Z, T fr.Element
    41  }
    42  
    43  const (
    44  	//following https://tools.ietf.org/html/rfc8032#section-3.1,
    45  	// an fr element x is negative if its binary encoding is
    46  	// lexicographically larger than -x.
    47  	mCompressedNegative = 0x80
    48  	mCompressedPositive = 0x00
    49  	mUnmask             = 0x7f
    50  
    51  	// size in byte of a compressed point (point.Y --> fr.Element)
    52  	sizePointCompressed = fr.Bytes
    53  )
    54  
    55  // Bytes returns the compressed point as a byte array
    56  // Follows https://tools.ietf.org/html/rfc8032#section-3.1,
    57  // as the twisted Edwards implementation is primarily used
    58  // for eddsa.
    59  func (p *PointAffine) Bytes() [sizePointCompressed]byte {
    60  
    61  	var res [sizePointCompressed]byte
    62  	var mask uint
    63  
    64  	y := p.Y.Bytes()
    65  
    66  	if p.X.LexicographicallyLargest() {
    67  		mask = mCompressedNegative
    68  	} else {
    69  		mask = mCompressedPositive
    70  	}
    71  	// p.Y must be in little endian
    72  	y[0] |= byte(mask) // msb of y
    73  	for i, j := 0, sizePointCompressed-1; i < j; i, j = i+1, j-1 {
    74  		y[i], y[j] = y[j], y[i]
    75  	}
    76  	subtle.ConstantTimeCopy(1, res[:], y[:])
    77  	return res
    78  }
    79  
    80  // Marshal converts p to a byte slice
    81  func (p *PointAffine) Marshal() []byte {
    82  	b := p.Bytes()
    83  	return b[:]
    84  }
    85  
    86  func computeX(y *fr.Element) (x fr.Element) {
    87  	initOnce.Do(initCurveParams)
    88  
    89  	var one, num, den fr.Element
    90  	one.SetOne()
    91  	num.Square(y)
    92  	den.Mul(&num, &curveParams.D)
    93  	num.Sub(&one, &num)
    94  	den.Sub(&curveParams.A, &den)
    95  	x.Div(&num, &den)
    96  	x.Sqrt(&x)
    97  	return
    98  }
    99  
   100  // SetBytes sets p from buf
   101  // len(buf) >= sizePointCompressed
   102  // buf contains the Y coordinate masked with a parity bit to recompute the X coordinate
   103  // from the curve equation. See Bytes() and https://tools.ietf.org/html/rfc8032#section-3.1
   104  // Returns the number of read bytes and an error if the buffer is too short.
   105  func (p *PointAffine) SetBytes(buf []byte) (int, error) {
   106  
   107  	if len(buf) < sizePointCompressed {
   108  		return 0, io.ErrShortBuffer
   109  	}
   110  	bufCopy := make([]byte, sizePointCompressed)
   111  	subtle.ConstantTimeCopy(1, bufCopy, buf[:sizePointCompressed])
   112  	for i, j := 0, sizePointCompressed-1; i < j; i, j = i+1, j-1 {
   113  		bufCopy[i], bufCopy[j] = bufCopy[j], bufCopy[i]
   114  	}
   115  	isLexicographicallyLargest := (mCompressedNegative&bufCopy[0])>>7 == 1
   116  	bufCopy[0] &= mUnmask
   117  	p.Y.SetBytes(bufCopy)
   118  	p.X = computeX(&p.Y)
   119  	if isLexicographicallyLargest {
   120  		if !p.X.LexicographicallyLargest() {
   121  			p.X.Neg(&p.X)
   122  		}
   123  	} else {
   124  		if p.X.LexicographicallyLargest() {
   125  			p.X.Neg(&p.X)
   126  		}
   127  	}
   128  
   129  	return sizePointCompressed, nil
   130  }
   131  
   132  // Unmarshal alias to SetBytes()
   133  func (p *PointAffine) Unmarshal(b []byte) error {
   134  	_, err := p.SetBytes(b)
   135  	return err
   136  }
   137  
   138  // Set sets p to p1 and return it
   139  func (p *PointAffine) Set(p1 *PointAffine) *PointAffine {
   140  	p.X.Set(&p1.X)
   141  	p.Y.Set(&p1.Y)
   142  	return p
   143  }
   144  
   145  // Equal returns true if p=p1 false otherwise
   146  func (p *PointAffine) Equal(p1 *PointAffine) bool {
   147  	return p.X.Equal(&p1.X) && p.Y.Equal(&p1.Y)
   148  }
   149  
   150  // IsZero returns true if p=0 false otherwise
   151  func (p *PointAffine) IsZero() bool {
   152  	var one fr.Element
   153  	one.SetOne()
   154  	return p.X.IsZero() && p.Y.Equal(&one)
   155  }
   156  
   157  // NewPointAffine creates a new instance of PointAffine
   158  func NewPointAffine(x, y fr.Element) PointAffine {
   159  	return PointAffine{x, y}
   160  }
   161  
   162  // IsOnCurve checks if a point is on the twisted Edwards curve
   163  func (p *PointAffine) IsOnCurve() bool {
   164  	initOnce.Do(initCurveParams)
   165  
   166  	var lhs, rhs, tmp fr.Element
   167  
   168  	tmp.Mul(&p.Y, &p.Y)
   169  	lhs.Mul(&p.X, &p.X)
   170  	mulByA(&lhs)
   171  	lhs.Add(&lhs, &tmp)
   172  
   173  	tmp.Mul(&p.X, &p.X).
   174  		Mul(&tmp, &p.Y).
   175  		Mul(&tmp, &p.Y).
   176  		Mul(&tmp, &curveParams.D)
   177  	rhs.SetOne().Add(&rhs, &tmp)
   178  
   179  	return lhs.Equal(&rhs)
   180  }
   181  
   182  // Neg sets p to -p1 and returns it
   183  func (p *PointAffine) Neg(p1 *PointAffine) *PointAffine {
   184  	p.X.Neg(&p1.X)
   185  	p.Y = p1.Y
   186  	return p
   187  }
   188  
   189  // Add adds two points (x,y), (u,v) on a twisted Edwards curve with parameters a, d
   190  // modifies p
   191  func (p *PointAffine) Add(p1, p2 *PointAffine) *PointAffine {
   192  	initOnce.Do(initCurveParams)
   193  
   194  	var xu, yv, xv, yu, dxyuv, one, denx, deny fr.Element
   195  	pRes := new(PointAffine)
   196  	xv.Mul(&p1.X, &p2.Y)
   197  	yu.Mul(&p1.Y, &p2.X)
   198  	pRes.X.Add(&xv, &yu)
   199  
   200  	xu.Mul(&p1.X, &p2.X)
   201  	mulByA(&xu)
   202  	yv.Mul(&p1.Y, &p2.Y)
   203  	pRes.Y.Sub(&yv, &xu)
   204  
   205  	dxyuv.Mul(&xv, &yu).Mul(&dxyuv, &curveParams.D)
   206  	one.SetOne()
   207  	denx.Add(&one, &dxyuv)
   208  	deny.Sub(&one, &dxyuv)
   209  
   210  	p.X.Div(&pRes.X, &denx)
   211  	p.Y.Div(&pRes.Y, &deny)
   212  
   213  	return p
   214  }
   215  
   216  // Double doubles point (x,y) on a twisted Edwards curve with parameters a, d
   217  // modifies p
   218  func (p *PointAffine) Double(p1 *PointAffine) *PointAffine {
   219  
   220  	p.Set(p1)
   221  	var xx, yy, xy, denum, two fr.Element
   222  
   223  	xx.Square(&p.X)
   224  	yy.Square(&p.Y)
   225  	xy.Mul(&p.X, &p.Y)
   226  	mulByA(&xx)
   227  	denum.Add(&xx, &yy)
   228  
   229  	p.X.Double(&xy).Div(&p.X, &denum)
   230  
   231  	two.SetOne().Double(&two)
   232  	denum.Neg(&denum).Add(&denum, &two)
   233  
   234  	p.Y.Sub(&yy, &xx).Div(&p.Y, &denum)
   235  
   236  	return p
   237  }
   238  
   239  // FromProj sets p in affine from p in projective
   240  func (p *PointAffine) FromProj(p1 *PointProj) *PointAffine {
   241  	var I fr.Element
   242  	I.Inverse(&p1.Z)
   243  	p.X.Mul(&p1.X, &I)
   244  	p.Y.Mul(&p1.Y, &I)
   245  	return p
   246  }
   247  
   248  // FromExtended sets p in affine from p in extended coordinates
   249  func (p *PointAffine) FromExtended(p1 *PointExtended) *PointAffine {
   250  	var I fr.Element
   251  	I.Inverse(&p1.Z)
   252  	p.X.Mul(&p1.X, &I)
   253  	p.Y.Mul(&p1.Y, &I)
   254  	return p
   255  }
   256  
   257  // ScalarMultiplication scalar multiplication of a point
   258  // p1 in affine coordinates with a scalar in big.Int
   259  func (p *PointAffine) ScalarMultiplication(p1 *PointAffine, scalar *big.Int) *PointAffine {
   260  
   261  	var p1Extended, resExtended PointExtended
   262  	p1Extended.FromAffine(p1)
   263  	resExtended.ScalarMultiplication(&p1Extended, scalar)
   264  	p.FromExtended(&resExtended)
   265  
   266  	return p
   267  }
   268  
   269  // setInfinity sets p to O (0:1)
   270  func (p *PointAffine) setInfinity() *PointAffine {
   271  	p.X.SetZero()
   272  	p.Y.SetOne()
   273  	return p
   274  }
   275  
   276  //-------- Projective coordinates
   277  
   278  // Set sets p to p1 and return it
   279  func (p *PointProj) Set(p1 *PointProj) *PointProj {
   280  	p.X.Set(&p1.X)
   281  	p.Y.Set(&p1.Y)
   282  	p.Z.Set(&p1.Z)
   283  	return p
   284  }
   285  
   286  // setInfinity sets p to O (0:1:1)
   287  func (p *PointProj) setInfinity() *PointProj {
   288  	p.X.SetZero()
   289  	p.Y.SetOne()
   290  	p.Z.SetOne()
   291  	return p
   292  }
   293  
   294  // Equal returns true if p=p1 false otherwise
   295  // If one point is on the affine chart Z=0 it returns false
   296  func (p *PointProj) Equal(p1 *PointProj) bool {
   297  	// If one point is infinity, the other must also be infinity.
   298  	if p.Z.IsZero() {
   299  		return p1.Z.IsZero()
   300  	}
   301  	// If the other point is infinity, return false since we can't
   302  	// the following checks would be incorrect.
   303  	if p1.Z.IsZero() {
   304  		return false
   305  	}
   306  
   307  	var lhs, rhs fr.Element
   308  	lhs.Mul(&p.X, &p1.Z)
   309  	rhs.Mul(&p1.X, &p.Z)
   310  	if !lhs.Equal(&rhs) {
   311  		return false
   312  	}
   313  	lhs.Mul(&p.Y, &p1.Z)
   314  	rhs.Mul(&p1.Y, &p.Z)
   315  
   316  	return lhs.Equal(&rhs)
   317  }
   318  
   319  // IsZero returns true if p=0 false otherwise
   320  func (p *PointProj) IsZero() bool {
   321  	return p.X.IsZero() && p.Y.Equal(&p.Z)
   322  }
   323  
   324  // Neg negates point (x,y) on a twisted Edwards curve with parameters a, d
   325  // modifies p
   326  func (p *PointProj) Neg(p1 *PointProj) *PointProj {
   327  	p.X.Neg(&p1.X)
   328  	p.Y = p1.Y
   329  	p.Z = p1.Z
   330  	return p
   331  }
   332  
   333  // FromAffine sets p in projective from p in affine
   334  func (p *PointProj) FromAffine(p1 *PointAffine) *PointProj {
   335  	p.X.Set(&p1.X)
   336  	p.Y.Set(&p1.Y)
   337  	p.Z.SetOne()
   338  	return p
   339  }
   340  
   341  // MixedAdd adds a point in projective to a point in affine coordinates
   342  // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
   343  func (p *PointProj) MixedAdd(p1 *PointProj, p2 *PointAffine) *PointProj {
   344  	initOnce.Do(initCurveParams)
   345  
   346  	var B, C, D, E, F, G, H, I fr.Element
   347  	B.Square(&p1.Z)
   348  	C.Mul(&p1.X, &p2.X)
   349  	D.Mul(&p1.Y, &p2.Y)
   350  	E.Mul(&curveParams.D, &C).Mul(&E, &D)
   351  	F.Sub(&B, &E)
   352  	G.Add(&B, &E)
   353  	H.Add(&p1.X, &p1.Y)
   354  	I.Add(&p2.X, &p2.Y)
   355  	p.X.Mul(&H, &I).
   356  		Sub(&p.X, &C).
   357  		Sub(&p.X, &D).
   358  		Mul(&p.X, &p1.Z).
   359  		Mul(&p.X, &F)
   360  	mulByA(&C)
   361  	p.Y.Sub(&D, &C).
   362  		Mul(&p.Y, &p1.Z).
   363  		Mul(&p.Y, &G)
   364  	p.Z.Mul(&F, &G)
   365  
   366  	return p
   367  }
   368  
   369  // Double adds points in projective coordinates
   370  // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
   371  func (p *PointProj) Double(p1 *PointProj) *PointProj {
   372  
   373  	var B, C, D, E, F, H, J fr.Element
   374  
   375  	B.Add(&p1.X, &p1.Y).Square(&B)
   376  	C.Square(&p1.X)
   377  	D.Square(&p1.Y)
   378  	E.Set(&C)
   379  	mulByA(&E)
   380  	F.Add(&E, &D)
   381  	H.Square(&p1.Z)
   382  	J.Sub(&F, &H).Sub(&J, &H)
   383  	p.X.Sub(&B, &C).
   384  		Sub(&p.X, &D).
   385  		Mul(&p.X, &J)
   386  	p.Y.Sub(&E, &D).Mul(&p.Y, &F)
   387  	p.Z.Mul(&F, &J)
   388  
   389  	return p
   390  }
   391  
   392  // Add adds points in projective coordinates
   393  // cf https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp
   394  func (p *PointProj) Add(p1, p2 *PointProj) *PointProj {
   395  	initOnce.Do(initCurveParams)
   396  
   397  	var A, B, C, D, E, F, G, H, I fr.Element
   398  	A.Mul(&p1.Z, &p2.Z)
   399  	B.Square(&A)
   400  	C.Mul(&p1.X, &p2.X)
   401  	D.Mul(&p1.Y, &p2.Y)
   402  	E.Mul(&curveParams.D, &C).Mul(&E, &D)
   403  	F.Sub(&B, &E)
   404  	G.Add(&B, &E)
   405  	H.Add(&p1.X, &p1.Y)
   406  	I.Add(&p2.X, &p2.Y)
   407  	p.X.Mul(&H, &I).
   408  		Sub(&p.X, &C).
   409  		Sub(&p.X, &D).
   410  		Mul(&p.X, &A).
   411  		Mul(&p.X, &F)
   412  	mulByA(&C)
   413  	C.Neg(&C)
   414  	p.Y.Add(&D, &C).
   415  		Mul(&p.Y, &A).
   416  		Mul(&p.Y, &G)
   417  	p.Z.Mul(&F, &G)
   418  
   419  	return p
   420  }
   421  
   422  // scalarMulWindowed scalar multiplication of a point
   423  // p1 in projective coordinates with a scalar in big.Int
   424  // using the windowed double-and-add method.
   425  func (p *PointProj) scalarMulWindowed(p1 *PointProj, scalar *big.Int) *PointProj {
   426  	var _scalar big.Int
   427  	_scalar.Set(scalar)
   428  	p.Set(p1)
   429  	if _scalar.Sign() == -1 {
   430  		_scalar.Neg(&_scalar)
   431  		p.Neg(p)
   432  	}
   433  	var resProj PointProj
   434  	resProj.setInfinity()
   435  	const wordSize = bits.UintSize
   436  	sWords := _scalar.Bits()
   437  
   438  	for i := len(sWords) - 1; i >= 0; i-- {
   439  		ithWord := sWords[i]
   440  		for k := 0; k < wordSize; k++ {
   441  			resProj.Double(&resProj)
   442  			kthBit := (ithWord >> (wordSize - 1 - k)) & 1
   443  			if kthBit == 1 {
   444  				resProj.Add(&resProj, p)
   445  			}
   446  		}
   447  	}
   448  
   449  	p.Set(&resProj)
   450  	return p
   451  }
   452  
   453  // ScalarMultiplication scalar multiplication of a point
   454  // p1 in projective coordinates with a scalar in big.Int
   455  func (p *PointProj) ScalarMultiplication(p1 *PointProj, scalar *big.Int) *PointProj {
   456  	return p.scalarMulWindowed(p1, scalar)
   457  }
   458  
   459  // ------- Extended coordinates
   460  
   461  // Set sets p to p1 and return it
   462  func (p *PointExtended) Set(p1 *PointExtended) *PointExtended {
   463  	p.X.Set(&p1.X)
   464  	p.Y.Set(&p1.Y)
   465  	p.T.Set(&p1.T)
   466  	p.Z.Set(&p1.Z)
   467  	return p
   468  }
   469  
   470  // IsZero returns true if p=0 false otherwise
   471  func (p *PointExtended) IsZero() bool {
   472  	return p.X.IsZero() && p.Y.Equal(&p.Z) && p.T.IsZero()
   473  }
   474  
   475  // Equal returns true if p=p1 false otherwise
   476  // If one point is on the affine chart Z=0 it returns false
   477  func (p *PointExtended) Equal(p1 *PointExtended) bool {
   478  	if p.Z.IsZero() || p1.Z.IsZero() {
   479  		return false
   480  	}
   481  	var pAffine, p1Affine PointAffine
   482  	pAffine.FromExtended(p)
   483  	p1Affine.FromExtended(p1)
   484  	return pAffine.Equal(&p1Affine)
   485  }
   486  
   487  // Neg negates point (x,y) on a twisted Edwards curve with parameters a, d
   488  // modifies p
   489  func (p *PointExtended) Neg(p1 *PointExtended) *PointExtended {
   490  	p.X.Neg(&p1.X)
   491  	p.Y = p1.Y
   492  	p.Z = p1.Z
   493  	p.T.Neg(&p1.T)
   494  	return p
   495  }
   496  
   497  // FromAffine sets p in projective from p in affine
   498  func (p *PointExtended) FromAffine(p1 *PointAffine) *PointExtended {
   499  	p.X.Set(&p1.X)
   500  	p.Y.Set(&p1.Y)
   501  	p.Z.SetOne()
   502  	p.T.Mul(&p1.X, &p1.Y)
   503  	return p
   504  }
   505  
   506  // Add adds points in extended coordinates
   507  // See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd
   508  func (p *PointExtended) Add(p1, p2 *PointExtended) *PointExtended {
   509  	var A, B, C, D, E, F, G, H, tmp fr.Element
   510  	A.Mul(&p1.X, &p2.X)
   511  	B.Mul(&p1.Y, &p2.Y)
   512  	C.Mul(&p1.T, &p2.T).Mul(&C, &curveParams.D)
   513  	D.Mul(&p1.Z, &p2.Z)
   514  	tmp.Add(&p1.X, &p1.Y)
   515  	E.Add(&p2.X, &p2.Y).
   516  		Mul(&E, &tmp).
   517  		Sub(&E, &A).
   518  		Sub(&E, &B)
   519  	F.Sub(&D, &C)
   520  	G.Add(&D, &C)
   521  	H.Set(&A)
   522  	mulByA(&H)
   523  	H.Sub(&B, &H)
   524  
   525  	p.X.Mul(&E, &F)
   526  	p.Y.Mul(&G, &H)
   527  	p.T.Mul(&E, &H)
   528  	p.Z.Mul(&F, &G)
   529  
   530  	return p
   531  }
   532  
   533  // MixedAdd adds a point in extended coordinates to a point in affine coordinates
   534  // See https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-madd-2008-hwcd-2
   535  func (p *PointExtended) MixedAdd(p1 *PointExtended, p2 *PointAffine) *PointExtended {
   536  	var A, B, C, D, E, F, G, H, tmp fr.Element
   537  
   538  	A.Mul(&p2.X, &p1.Z)
   539  	B.Mul(&p2.Y, &p1.Z)
   540  
   541  	if p1.X.Equal(&A) && p1.Y.Equal(&B) {
   542  		p.MixedDouble(p1)
   543  		return p
   544  	}
   545  
   546  	A.Mul(&p1.X, &p2.X)
   547  	B.Mul(&p1.Y, &p2.Y)
   548  	C.Mul(&p1.Z, &p2.X).
   549  		Mul(&C, &p2.Y)
   550  	D.Set(&p1.T)
   551  	E.Add(&D, &C)
   552  	tmp.Sub(&p1.X, &p1.Y)
   553  	F.Add(&p2.X, &p2.Y).
   554  		Mul(&F, &tmp).
   555  		Add(&F, &B).
   556  		Sub(&F, &A)
   557  	G.Set(&A)
   558  	mulByA(&G)
   559  	G.Add(&G, &B)
   560  	H.Sub(&D, &C)
   561  
   562  	p.X.Mul(&E, &F)
   563  	p.Y.Mul(&G, &H)
   564  	p.T.Mul(&E, &H)
   565  	p.Z.Mul(&F, &G)
   566  
   567  	return p
   568  }
   569  
   570  // Double adds points in extended coordinates
   571  // Dedicated doubling
   572  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd
   573  func (p *PointExtended) Double(p1 *PointExtended) *PointExtended {
   574  
   575  	var A, B, C, D, E, F, G, H fr.Element
   576  
   577  	A.Square(&p1.X)
   578  	B.Square(&p1.Y)
   579  	C.Square(&p1.Z).
   580  		Double(&C)
   581  	D.Set(&A)
   582  	mulByA(&D)
   583  	E.Add(&p1.X, &p1.Y).
   584  		Square(&E).
   585  		Sub(&E, &A).
   586  		Sub(&E, &B)
   587  	G.Add(&D, &B)
   588  	F.Sub(&G, &C)
   589  	H.Sub(&D, &B)
   590  
   591  	p.X.Mul(&E, &F)
   592  	p.Y.Mul(&G, &H)
   593  	p.T.Mul(&H, &E)
   594  	p.Z.Mul(&F, &G)
   595  
   596  	return p
   597  }
   598  
   599  // MixedDouble adds points in extended coordinates
   600  // Dedicated mixed doubling
   601  // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-mdbl-2008-hwcd
   602  func (p *PointExtended) MixedDouble(p1 *PointExtended) *PointExtended {
   603  
   604  	var A, B, D, E, G, H, two fr.Element
   605  	two.SetUint64(2)
   606  
   607  	A.Square(&p1.X)
   608  	B.Square(&p1.Y)
   609  	D.Set(&A)
   610  	mulByA(&D)
   611  	E.Add(&p1.X, &p1.Y).
   612  		Square(&E).
   613  		Sub(&E, &A).
   614  		Sub(&E, &B)
   615  	G.Add(&D, &B)
   616  	H.Sub(&D, &B)
   617  
   618  	p.X.Sub(&G, &two).
   619  		Mul(&p.X, &E)
   620  	p.Y.Mul(&G, &H)
   621  	p.T.Mul(&H, &E)
   622  	p.Z.Square(&G).
   623  		Sub(&p.Z, &G).
   624  		Sub(&p.Z, &G)
   625  
   626  	return p
   627  }
   628  
   629  // setInfinity sets p to O (0:1:1:0)
   630  func (p *PointExtended) setInfinity() *PointExtended {
   631  	p.X.SetZero()
   632  	p.Y.SetOne()
   633  	p.Z.SetOne()
   634  	p.T.SetZero()
   635  	return p
   636  }
   637  
   638  // scalarMulWindowed scalar multiplication of a point
   639  // p1 in extended coordinates with a scalar in big.Int
   640  // using the windowed double-and-add method.
   641  func (p *PointExtended) scalarMulWindowed(p1 *PointExtended, scalar *big.Int) *PointExtended {
   642  	var _scalar big.Int
   643  	_scalar.Set(scalar)
   644  	p.Set(p1)
   645  	if _scalar.Sign() == -1 {
   646  		_scalar.Neg(&_scalar)
   647  		p.Neg(p)
   648  	}
   649  	var resExtended PointExtended
   650  	resExtended.setInfinity()
   651  	const wordSize = bits.UintSize
   652  	sWords := _scalar.Bits()
   653  
   654  	for i := len(sWords) - 1; i >= 0; i-- {
   655  		ithWord := sWords[i]
   656  		for k := 0; k < wordSize; k++ {
   657  			resExtended.Double(&resExtended)
   658  			kthBit := (ithWord >> (wordSize - 1 - k)) & 1
   659  			if kthBit == 1 {
   660  				resExtended.Add(&resExtended, p)
   661  			}
   662  		}
   663  	}
   664  
   665  	p.Set(&resExtended)
   666  	return p
   667  }
   668  
   669  // ScalarMultiplication scalar multiplication of a point
   670  // p1 in extended coordinates with a scalar in big.Int
   671  func (p *PointExtended) ScalarMultiplication(p1 *PointExtended, scalar *big.Int) *PointExtended {
   672  	return p.scalarMulWindowed(p1, scalar)
   673  }