github.com/ethereum/go-ethereum@v1.16.1/crypto/bn256/gnark/g2.go (about)

     1  package bn256
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/consensys/gnark-crypto/ecc/bn254"
     7  )
     8  
     9  // G2 is the affine representation of a G2 group element.
    10  //
    11  // Since this code is used for precompiles, using Jacobian
    12  // points are not beneficial because there are no intermediate
    13  // points and G2 in particular is only used for the pairing input.
    14  //
    15  // Note: We also use this struct so that we can conform to the existing API
    16  // that the precompiles want.
    17  type G2 struct {
    18  	inner bn254.G2Affine
    19  }
    20  
    21  // Unmarshal deserializes `buf` into `g`
    22  //
    23  // The input is expected to be in the EVM format:
    24  // 128 bytes: [32-byte x.1][32-byte x.0][32-byte y.1][32-byte y.0]
    25  // where each value is a big-endian integer.
    26  //
    27  // This method also checks whether the point is on the
    28  // curve and in the prime order subgroup.
    29  func (g *G2) Unmarshal(buf []byte) (int, error) {
    30  	if len(buf) < 128 {
    31  		return 0, errors.New("invalid G2 point size")
    32  	}
    33  
    34  	if allZeroes(buf[:128]) {
    35  		// point at infinity
    36  		g.inner.X.A0.SetZero()
    37  		g.inner.X.A1.SetZero()
    38  		g.inner.Y.A0.SetZero()
    39  		g.inner.Y.A1.SetZero()
    40  		return 128, nil
    41  	}
    42  	if err := g.inner.X.A1.SetBytesCanonical(buf[0:32]); err != nil {
    43  		return 0, err
    44  	}
    45  	if err := g.inner.X.A0.SetBytesCanonical(buf[32:64]); err != nil {
    46  		return 0, err
    47  	}
    48  	if err := g.inner.Y.A1.SetBytesCanonical(buf[64:96]); err != nil {
    49  		return 0, err
    50  	}
    51  	if err := g.inner.Y.A0.SetBytesCanonical(buf[96:128]); err != nil {
    52  		return 0, err
    53  	}
    54  
    55  	if !g.inner.IsOnCurve() {
    56  		return 0, errors.New("point is not on curve")
    57  	}
    58  	if !g.inner.IsInSubGroup() {
    59  		return 0, errors.New("point is not in correct subgroup")
    60  	}
    61  	return 128, nil
    62  }
    63  
    64  // Marshal serializes the point into a byte slice.
    65  //
    66  // The output is in EVM format: 128 bytes total.
    67  // [32-byte x.1][32-byte x.0][32-byte y.1][32-byte y.0]
    68  // where each value is a big-endian integer.
    69  func (g *G2) Marshal() []byte {
    70  	output := make([]byte, 128)
    71  
    72  	xA1Bytes := g.inner.X.A1.Bytes()
    73  	copy(output[:32], xA1Bytes[:])
    74  
    75  	xA0Bytes := g.inner.X.A0.Bytes()
    76  	copy(output[32:64], xA0Bytes[:])
    77  
    78  	yA1Bytes := g.inner.Y.A1.Bytes()
    79  	copy(output[64:96], yA1Bytes[:])
    80  
    81  	yA0Bytes := g.inner.Y.A0.Bytes()
    82  	copy(output[96:128], yA0Bytes[:])
    83  
    84  	return output
    85  }