github.com/amazechain/amc@v0.1.3/common/crypto/bls12381/g1.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  //nolint:golint
    18  package bls12381
    19  
    20  import (
    21  	"errors"
    22  	"math"
    23  	"math/big"
    24  )
    25  
    26  // PointG1 is type for point in G1.
    27  // PointG1 is both used for Affine and Jacobian point representation.
    28  // If z is equal to one the point is considered as in affine form.
    29  type PointG1 [3]fe
    30  
    31  func (p *PointG1) Set(p2 *PointG1) *PointG1 {
    32  	p[0].set(&p2[0])
    33  	p[1].set(&p2[1])
    34  	p[2].set(&p2[2])
    35  	return p
    36  }
    37  
    38  // Zero returns G1 point in point at infinity representation
    39  func (p *PointG1) Zero() *PointG1 {
    40  	p[0].zero()
    41  	p[1].one()
    42  	p[2].zero()
    43  	return p
    44  }
    45  
    46  type tempG1 struct {
    47  	t [9]*fe
    48  }
    49  
    50  // G1 is struct for G1 group.
    51  type G1 struct {
    52  	tempG1
    53  }
    54  
    55  // NewG1 constructs a new G1 instance.
    56  func NewG1() *G1 {
    57  	t := newTempG1()
    58  	return &G1{t}
    59  }
    60  
    61  func newTempG1() tempG1 {
    62  	t := [9]*fe{}
    63  	for i := 0; i < 9; i++ {
    64  		t[i] = &fe{}
    65  	}
    66  	return tempG1{t}
    67  }
    68  
    69  // Q returns group order in big.Int.
    70  func (g *G1) Q() *big.Int {
    71  	return new(big.Int).Set(q)
    72  }
    73  
    74  func (g *G1) fromBytesUnchecked(in []byte) (*PointG1, error) {
    75  	p0, err := fromBytes(in[:48])
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	p1, err := fromBytes(in[48:])
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	p2 := new(fe).one()
    84  	return &PointG1{*p0, *p1, *p2}, nil
    85  }
    86  
    87  // FromBytes constructs a new point given uncompressed byte input.
    88  // FromBytes does not take zcash flags into account.
    89  // Byte input expected to be larger than 96 bytes.
    90  // First 96 bytes should be concatenation of x and y values.
    91  // Point (0, 0) is considered as infinity.
    92  func (g *G1) FromBytes(in []byte) (*PointG1, error) {
    93  	if len(in) != 96 {
    94  		return nil, errors.New("input string should be equal or larger than 96")
    95  	}
    96  	p0, err := fromBytes(in[:48])
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	p1, err := fromBytes(in[48:])
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	// check if given input points to infinity
   105  	if p0.isZero() && p1.isZero() {
   106  		return g.Zero(), nil
   107  	}
   108  	p2 := new(fe).one()
   109  	p := &PointG1{*p0, *p1, *p2}
   110  	if !g.IsOnCurve(p) {
   111  		return nil, errors.New("point is not on curve")
   112  	}
   113  	return p, nil
   114  }
   115  
   116  // DecodePoint given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point.
   117  func (g *G1) DecodePoint(in []byte) (*PointG1, error) {
   118  	if len(in) != 128 {
   119  		return nil, errors.New("invalid g1 point length")
   120  	}
   121  	pointBytes := make([]byte, 96)
   122  	// decode x
   123  	xBytes, err := decodeFieldElement(in[:64])
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	// decode y
   128  	yBytes, err := decodeFieldElement(in[64:])
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	copy(pointBytes[:48], xBytes)
   133  	copy(pointBytes[48:], yBytes)
   134  	return g.FromBytes(pointBytes)
   135  }
   136  
   137  // ToBytes serializes a point into bytes in uncompressed form.
   138  // ToBytes does not take zcash flags into account.
   139  // ToBytes returns (0, 0) if point is infinity.
   140  func (g *G1) ToBytes(p *PointG1) []byte {
   141  	out := make([]byte, 96)
   142  	if g.IsZero(p) {
   143  		return out
   144  	}
   145  	g.Affine(p)
   146  	copy(out[:48], toBytes(&p[0]))
   147  	copy(out[48:], toBytes(&p[1]))
   148  	return out
   149  }
   150  
   151  // EncodePoint encodes a point into 128 bytes.
   152  func (g *G1) EncodePoint(p *PointG1) []byte {
   153  	outRaw := g.ToBytes(p)
   154  	out := make([]byte, 128)
   155  	// encode x
   156  	copy(out[16:], outRaw[:48])
   157  	// encode y
   158  	copy(out[64+16:], outRaw[48:])
   159  	return out
   160  }
   161  
   162  // New creates a new G1 Point which is equal to zero in other words point at infinity.
   163  func (g *G1) New() *PointG1 {
   164  	return g.Zero()
   165  }
   166  
   167  // Zero returns a new G1 Point which is equal to point at infinity.
   168  func (g *G1) Zero() *PointG1 {
   169  	return new(PointG1).Zero()
   170  }
   171  
   172  // One returns a new G1 Point which is equal to generator point.
   173  func (g *G1) One() *PointG1 {
   174  	p := &PointG1{}
   175  	return p.Set(&g1One)
   176  }
   177  
   178  // IsZero returns true if given point is equal to zero.
   179  func (g *G1) IsZero(p *PointG1) bool {
   180  	return p[2].isZero()
   181  }
   182  
   183  // Equal checks if given two G1 point is equal in their affine form.
   184  func (g *G1) Equal(p1, p2 *PointG1) bool {
   185  	if g.IsZero(p1) {
   186  		return g.IsZero(p2)
   187  	}
   188  	if g.IsZero(p2) {
   189  		return g.IsZero(p1)
   190  	}
   191  	t := g.t
   192  	square(t[0], &p1[2])
   193  	square(t[1], &p2[2])
   194  	mul(t[2], t[0], &p2[0])
   195  	mul(t[3], t[1], &p1[0])
   196  	mul(t[0], t[0], &p1[2])
   197  	mul(t[1], t[1], &p2[2])
   198  	mul(t[1], t[1], &p1[1])
   199  	mul(t[0], t[0], &p2[1])
   200  	return t[0].equal(t[1]) && t[2].equal(t[3])
   201  }
   202  
   203  // InCorrectSubgroup checks whether given point is in correct subgroup.
   204  func (g *G1) InCorrectSubgroup(p *PointG1) bool {
   205  	tmp := &PointG1{}
   206  	g.MulScalar(tmp, p, q)
   207  	return g.IsZero(tmp)
   208  }
   209  
   210  // IsOnCurve checks a G1 point is on curve.
   211  func (g *G1) IsOnCurve(p *PointG1) bool {
   212  	if g.IsZero(p) {
   213  		return true
   214  	}
   215  	t := g.t
   216  	square(t[0], &p[1])
   217  	square(t[1], &p[0])
   218  	mul(t[1], t[1], &p[0])
   219  	square(t[2], &p[2])
   220  	square(t[3], t[2])
   221  	mul(t[2], t[2], t[3])
   222  	mul(t[2], b, t[2])
   223  	add(t[1], t[1], t[2])
   224  	return t[0].equal(t[1])
   225  }
   226  
   227  // IsAffine checks a G1 point whether it is in affine form.
   228  func (g *G1) IsAffine(p *PointG1) bool {
   229  	return p[2].isOne()
   230  }
   231  
   232  // Add adds two G1 points p1, p2 and assigns the result to point at first argument.
   233  func (g *G1) Affine(p *PointG1) *PointG1 {
   234  	if g.IsZero(p) {
   235  		return p
   236  	}
   237  	if !g.IsAffine(p) {
   238  		t := g.t
   239  		inverse(t[0], &p[2])
   240  		square(t[1], t[0])
   241  		mul(&p[0], &p[0], t[1])
   242  		mul(t[0], t[0], t[1])
   243  		mul(&p[1], &p[1], t[0])
   244  		p[2].one()
   245  	}
   246  	return p
   247  }
   248  
   249  // Add adds two G1 points p1, p2 and assigns the result to point at first argument.
   250  func (g *G1) Add(r, p1, p2 *PointG1) *PointG1 {
   251  	// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#addition-add-2007-bl
   252  	if g.IsZero(p1) {
   253  		return r.Set(p2)
   254  	}
   255  	if g.IsZero(p2) {
   256  		return r.Set(p1)
   257  	}
   258  	t := g.t
   259  	square(t[7], &p1[2])
   260  	mul(t[1], &p2[0], t[7])
   261  	mul(t[2], &p1[2], t[7])
   262  	mul(t[0], &p2[1], t[2])
   263  	square(t[8], &p2[2])
   264  	mul(t[3], &p1[0], t[8])
   265  	mul(t[4], &p2[2], t[8])
   266  	mul(t[2], &p1[1], t[4])
   267  	if t[1].equal(t[3]) {
   268  		if t[0].equal(t[2]) {
   269  			return g.Double(r, p1)
   270  		}
   271  		return r.Zero()
   272  	}
   273  	sub(t[1], t[1], t[3])
   274  	double(t[4], t[1])
   275  	square(t[4], t[4])
   276  	mul(t[5], t[1], t[4])
   277  	sub(t[0], t[0], t[2])
   278  	double(t[0], t[0])
   279  	square(t[6], t[0])
   280  	sub(t[6], t[6], t[5])
   281  	mul(t[3], t[3], t[4])
   282  	double(t[4], t[3])
   283  	sub(&r[0], t[6], t[4])
   284  	sub(t[4], t[3], &r[0])
   285  	mul(t[6], t[2], t[5])
   286  	double(t[6], t[6])
   287  	mul(t[0], t[0], t[4])
   288  	sub(&r[1], t[0], t[6])
   289  	add(t[0], &p1[2], &p2[2])
   290  	square(t[0], t[0])
   291  	sub(t[0], t[0], t[7])
   292  	sub(t[0], t[0], t[8])
   293  	mul(&r[2], t[0], t[1])
   294  	return r
   295  }
   296  
   297  // Double doubles a G1 point p and assigns the result to the point at first argument.
   298  func (g *G1) Double(r, p *PointG1) *PointG1 {
   299  	// http://www.hyperelliptic.org/EFD/gp/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
   300  	if g.IsZero(p) {
   301  		return r.Set(p)
   302  	}
   303  	t := g.t
   304  	square(t[0], &p[0])
   305  	square(t[1], &p[1])
   306  	square(t[2], t[1])
   307  	add(t[1], &p[0], t[1])
   308  	square(t[1], t[1])
   309  	sub(t[1], t[1], t[0])
   310  	sub(t[1], t[1], t[2])
   311  	double(t[1], t[1])
   312  	double(t[3], t[0])
   313  	add(t[0], t[3], t[0])
   314  	square(t[4], t[0])
   315  	double(t[3], t[1])
   316  	sub(&r[0], t[4], t[3])
   317  	sub(t[1], t[1], &r[0])
   318  	double(t[2], t[2])
   319  	double(t[2], t[2])
   320  	double(t[2], t[2])
   321  	mul(t[0], t[0], t[1])
   322  	sub(t[1], t[0], t[2])
   323  	mul(t[0], &p[1], &p[2])
   324  	r[1].set(t[1])
   325  	double(&r[2], t[0])
   326  	return r
   327  }
   328  
   329  // Neg negates a G1 point p and assigns the result to the point at first argument.
   330  func (g *G1) Neg(r, p *PointG1) *PointG1 {
   331  	r[0].set(&p[0])
   332  	r[2].set(&p[2])
   333  	neg(&r[1], &p[1])
   334  	return r
   335  }
   336  
   337  // Sub subtracts two G1 points p1, p2 and assigns the result to point at first argument.
   338  func (g *G1) Sub(c, a, b *PointG1) *PointG1 {
   339  	d := &PointG1{}
   340  	g.Neg(d, b)
   341  	g.Add(c, a, d)
   342  	return c
   343  }
   344  
   345  // MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument.
   346  func (g *G1) MulScalar(c, p *PointG1, e *big.Int) *PointG1 {
   347  	q, n := &PointG1{}, &PointG1{}
   348  	n.Set(p)
   349  	l := e.BitLen()
   350  	for i := 0; i < l; i++ {
   351  		if e.Bit(i) == 1 {
   352  			g.Add(q, q, n)
   353  		}
   354  		g.Double(n, n)
   355  	}
   356  	return c.Set(q)
   357  }
   358  
   359  // ClearCofactor maps given a G1 point to correct subgroup
   360  func (g *G1) ClearCofactor(p *PointG1) {
   361  	g.MulScalar(p, p, cofactorEFFG1)
   362  }
   363  
   364  // MultiExp calculates multi exponentiation. Given pairs of G1 point and scalar values
   365  // (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n
   366  // Length of points and scalars are expected to be equal, otherwise an error is returned.
   367  // Result is assigned to point at first argument.
   368  func (g *G1) MultiExp(r *PointG1, points []*PointG1, powers []*big.Int) (*PointG1, error) {
   369  	if len(points) != len(powers) {
   370  		return nil, errors.New("point and scalar vectors should be in same length")
   371  	}
   372  	var c uint32 = 3
   373  	if len(powers) >= 32 {
   374  		c = uint32(math.Ceil(math.Log10(float64(len(powers)))))
   375  	}
   376  	bucketSize, numBits := (1<<c)-1, uint32(g.Q().BitLen())
   377  	windows := make([]*PointG1, numBits/c+1)
   378  	bucket := make([]*PointG1, bucketSize)
   379  	acc, sum := g.New(), g.New()
   380  	for i := 0; i < bucketSize; i++ {
   381  		bucket[i] = g.New()
   382  	}
   383  	mask := (uint64(1) << c) - 1
   384  	j := 0
   385  	var cur uint32
   386  	for cur <= numBits {
   387  		acc.Zero()
   388  		bucket = make([]*PointG1, (1<<c)-1)
   389  		for i := 0; i < len(bucket); i++ {
   390  			bucket[i] = g.New()
   391  		}
   392  		for i := 0; i < len(powers); i++ {
   393  			s0 := powers[i].Uint64()
   394  			index := uint(s0 & mask)
   395  			if index != 0 {
   396  				g.Add(bucket[index-1], bucket[index-1], points[i])
   397  			}
   398  			powers[i] = new(big.Int).Rsh(powers[i], uint(c))
   399  		}
   400  		sum.Zero()
   401  		for i := len(bucket) - 1; i >= 0; i-- {
   402  			g.Add(sum, sum, bucket[i])
   403  			g.Add(acc, acc, sum)
   404  		}
   405  		windows[j] = g.New()
   406  		windows[j].Set(acc)
   407  		j++
   408  		cur += c
   409  	}
   410  	acc.Zero()
   411  	for i := len(windows) - 1; i >= 0; i-- {
   412  		for j := uint32(0); j < c; j++ {
   413  			g.Double(acc, acc)
   414  		}
   415  		g.Add(acc, acc, windows[i])
   416  	}
   417  	return r.Set(acc), nil
   418  }
   419  
   420  // MapToCurve given a byte slice returns a valid G1 point.
   421  // This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method.
   422  // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06
   423  // Input byte slice should be a valid field element, otherwise an error is returned.
   424  func (g *G1) MapToCurve(in []byte) (*PointG1, error) {
   425  	u, err := fromBytes(in)
   426  	if err != nil {
   427  		return nil, err
   428  	}
   429  	x, y := swuMapG1(u)
   430  	isogenyMapG1(x, y)
   431  	one := new(fe).one()
   432  	p := &PointG1{*x, *y, *one}
   433  	g.ClearCofactor(p)
   434  	return g.Affine(p), nil
   435  }