11package bn256
22
33import (
4+ "errors"
5+
46 "github.com/consensys/gnark-crypto/ecc/bn254"
57)
68
@@ -18,21 +20,66 @@ type G2 struct {
1820
1921// Unmarshal deserializes `buf` into `g`
2022//
21- // Note: whether the deserialization is of a compressed
22- // or an uncompressed point, is encoded in the bytes.
23- //
24- // For our purpose, the point will always be serialized
25- // as uncompressed, ie 128 bytes.
23+ // The input is expected to be in the EVM format:
24+ // 128 bytes: [32-byte x.0][32-byte x.1][32-byte y.0][32-byte y.1]
25+ // where each value is a big-endian integer.
2626//
2727// This method also checks whether the point is on the
2828// curve and in the prime order subgroup.
2929func (g * G2 ) Unmarshal (buf []byte ) (int , error ) {
30- return g .inner .SetBytes (buf )
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 .A0 .SetBytesCanonical (buf [0 :32 ]); err != nil {
43+ return 0 , err
44+ }
45+ if err := g .inner .X .A1 .SetBytesCanonical (buf [32 :64 ]); err != nil {
46+ return 0 , err
47+ }
48+ if err := g .inner .Y .A0 .SetBytesCanonical (buf [64 :96 ]); err != nil {
49+ return 0 , err
50+ }
51+ if err := g .inner .Y .A1 .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
3162}
3263
3364// Marshal serializes the point into a byte slice.
3465//
35- // Note: The point is serialized as uncompressed.
66+ // The output is in EVM format: 128 bytes total.
67+ // [32-byte x.0][32-byte x.1][32-byte y.0][32-byte y.1]
68+ // where each value is a big-endian integer.
3669func (g * G2 ) Marshal () []byte {
37- return g .inner .Marshal ()
70+ output := make ([]byte , 128 )
71+
72+ xA0Bytes := g .inner .X .A0 .Bytes ()
73+ copy (output [:32 ], xA0Bytes [:])
74+
75+ xA1Bytes := g .inner .X .A1 .Bytes ()
76+ copy (output [32 :64 ], xA1Bytes [:])
77+
78+ yA0Bytes := g .inner .Y .A0 .Bytes ()
79+ copy (output [64 :96 ], yA0Bytes [:])
80+
81+ yA1Bytes := g .inner .Y .A1 .Bytes ()
82+ copy (output [96 :128 ], yA1Bytes [:])
83+
84+ return output
3885}
0 commit comments