github.com/ethereum/go-ethereum@v1.16.1/crypto/bn256/gnark/g1.go (about) 1 package bn256 2 3 import ( 4 "errors" 5 "math/big" 6 7 "github.com/consensys/gnark-crypto/ecc/bn254" 8 ) 9 10 // G1 is the affine representation of a G1 group element. 11 // 12 // Since this code is used for precompiles, using Jacobian 13 // points are not beneficial because there are no intermediate 14 // points to allow us to save on inversions. 15 // 16 // Note: We also use this struct so that we can conform to the existing API 17 // that the precompiles want. 18 type G1 struct { 19 inner bn254.G1Affine 20 } 21 22 // Add adds `a` and `b` together, storing the result in `g` 23 func (g *G1) Add(a, b *G1) { 24 g.inner.Add(&a.inner, &b.inner) 25 } 26 27 // ScalarMult computes the scalar multiplication between `a` and 28 // `scalar`, storing the result in `g` 29 func (g *G1) ScalarMult(a *G1, scalar *big.Int) { 30 g.inner.ScalarMultiplication(&a.inner, scalar) 31 } 32 33 // Unmarshal deserializes `buf` into `g` 34 // 35 // The input is expected to be in the EVM format: 36 // 64 bytes: [32-byte x coordinate][32-byte y coordinate] 37 // where each coordinate is in big-endian format. 38 // 39 // This method also checks whether the point is on the 40 // curve and in the prime order subgroup. 41 func (g *G1) Unmarshal(buf []byte) (int, error) { 42 if len(buf) < 64 { 43 return 0, errors.New("invalid G1 point size") 44 } 45 46 if allZeroes(buf[:64]) { 47 // point at infinity 48 g.inner.X.SetZero() 49 g.inner.Y.SetZero() 50 return 64, nil 51 } 52 53 if err := g.inner.X.SetBytesCanonical(buf[:32]); err != nil { 54 return 0, err 55 } 56 if err := g.inner.Y.SetBytesCanonical(buf[32:64]); err != nil { 57 return 0, err 58 } 59 60 if !g.inner.IsOnCurve() { 61 return 0, errors.New("point is not on curve") 62 } 63 if !g.inner.IsInSubGroup() { 64 return 0, errors.New("point is not in correct subgroup") 65 } 66 return 64, nil 67 } 68 69 // Marshal serializes the point into a byte slice. 70 // 71 // The output is in EVM format: 64 bytes total. 72 // [32-byte x coordinate][32-byte y coordinate] 73 // where each coordinate is a big-endian integer padded to 32 bytes. 74 func (p *G1) Marshal() []byte { 75 output := make([]byte, 64) 76 77 xBytes := p.inner.X.Bytes() 78 copy(output[:32], xBytes[:]) 79 80 yBytes := p.inner.Y.Bytes() 81 copy(output[32:64], yBytes[:]) 82 83 return output 84 } 85 86 func allZeroes(buf []byte) bool { 87 for i := range buf { 88 if buf[i] != 0 { 89 return false 90 } 91 } 92 return true 93 }