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 }