You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix BN254 G1/G2 Point Encoding and Decoding (#1614)
### What
Corrects the serialization format for BN254 G1 and G2 points to match
[cap-74](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0074.md),
which is modeled after EVM precompile specifications
([eip-196](https://eips.ethereum.org/EIPS/eip-196#encoding) and
[197](https://eips.ethereum.org/EIPS/eip-197#encoding)):
- All field elements now use big-endian encoding
- Extension field elements (G2 points) are serialized with the imaginary
component (c1) followed by the real component (c0)
- The two flag bits are unset -- point-at-infinity is represented as
`(0, 0)`, serialized as a zero-byte array; and a point with negative y
component does not have the y-sign flag (bit 0) set.
Additional testing:
- Added additional external hardcoded tests from
https://www.evm.codes/precompiled
- More Serialization round-trip validation including invalid inputs and
edge cases
**Acknowledgments**
Big thanks to @Oghma for testing the preview version, discovering this
bug, and reporting it to us.
---------
Co-authored-by: Siddharth Suresh <[email protected]>
Copy file name to clipboardExpand all lines: soroban-env-common/env.json
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -2367,7 +2367,7 @@
2367
2367
{ "name": "point2", "type": "BytesObject" }
2368
2368
],
2369
2369
"return": "BytesObject",
2370
-
"docs": "Adds two BN254 G1 points; encoding is 64-byte be_bytes(X)||be_bytes(Y); infinity is all-zeroes. No subgroup check.",
2370
+
"docs": "Adds two BN254 G1 points. G1 encoding: 64-byte uncompressed format: be_bytes(X)||be_bytes(Y), where X and Y are 32-byte big-endian Fp field elements. The two flag bits (0x80 and 0x40) of the first byte must be unset -- infinity is represented as 64 zero bytes. Points must be on curve with no subgroup check needed (always in subgroup)",
2371
2371
"min_supported_protocol": 25
2372
2372
},
2373
2373
{
@@ -2378,7 +2378,7 @@
2378
2378
{ "name": "scalar", "type": "U256Val" }
2379
2379
],
2380
2380
"return": "BytesObject",
2381
-
"docs": "Multiplies a BN254 G1 point by a scalar (Fr); same encoding as bn254_g1_add.",
2381
+
"docs": "Multiplies a BN254 G1 point by a scalar from the scalar field Fr. The point uses the same 64-byte encoding as bn254_g1_add. The scalar is a U256Val representing a 256-bit integer that is reduced modulo the Fr field order.",
2382
2382
"min_supported_protocol": 25
2383
2383
},
2384
2384
{
@@ -2389,7 +2389,7 @@
2389
2389
{ "name": "vp2", "type": "VecObject" }
2390
2390
],
2391
2391
"return": "Bool",
2392
-
"docs": "Performs BN254 pairings over vectors of G1 and G2 points; returns true iff product equals 1 in Fq12.",
2392
+
"docs": "Performs BN254 multi-pairing check over equal-length non-empty vectors of G1 and G2 points. Returns true iff the product of pairings e(G1[0],G2[0])*...*e(G1[n-1],G2[n-1]) equals 1 in Fq12. G1 encoding: 64 bytes as in bn254_g1_add. G2 encoding: 128-byte uncompressed format: be_bytes(X)||be_bytes(Y), where X and Y are Fp2 elements (64 bytes each). Fp2 element encoding: be_bytes(c1)||be_bytes(c0) where c0 is the real part and c1 is the imaginary part (each 32-byte big-endian Fp). The two flag bits (0x80 and 0x40) of the first byte must be unset -- G2 infinity is 128 zero bytes. G2 points must be on curve AND in the correct subgroup.",
0 commit comments