Arithmetic on the BLS12-381 curve, in pure Elixir, for the EIP-2537
precompiles (0x0B–0x11) and the EIP-4844 point-evaluation precompile
(0x0A).
Field elements are plain integers in [0, p), kept canonical after every
operation. The extension fields form the usual tower:
- Fp2 = Fp[u] / (u² + 1), as
{a0, a1}= a0 + a1·u - Fp6 = Fp2[v] / (v³ − ξ) with ξ = 1 + u, as
{c0, c1, c2} - Fp12 = Fp6[w] / (w² − v), as
{c0, c1}
G1 is the order-r subgroup of E: y² = x³ + 4 over Fp. G2 is the order-r subgroup of the M-type sextic twist E': y² = x³ + 4(1 + u) over Fp2. A G1 point has integer coordinates and a G2 point Fp2 (tuple) coordinates, and every point function here works on both: the field operations underneath dispatch on the coordinate type, so the point formulas, scalar multiplication, MSM, and map-to-curve are written once.
Affine points are {x, y} or :infinity. Internally points are in
Jacobian coordinates (x = X/Z², y = Y/Z³), so additions need no inversion.
The structure mirrors EEVM.Precompiles.BN256.Curve. The pairing follows
arkworks' ark-ec BLS12 model (M-type twist, x < 0), map-to-curve follows
RFC 9380, and the subgroup checks are Scott's endomorphism tests.
Summary
Types
An element a0 + a1·u of Fp2.
An element of Fp, in [0, p).
An affine G1 point (on E) or the point at infinity.
An affine G2 point (on the twist E') or the point at infinity.
An affine point of either group.
Functions
Adds two affine points of the same group, both on the curve.
Returns the base field modulus p.
Decompresses a 48-byte G1 point in the ZCash serialization used by KZG
commitments and proofs (the consensus specs' bytes_to_kzg_commitment).
Returns the standard generator of G1.
Returns the standard generator of G2.
Returns whether a point already known to be on its curve lies in the order-r subgroup (G1 or G2).
Maps an Fp2 element to a G2 point (EIP-2537 MAP_FP2_TO_G2): the
simplified SWU map onto E2', the 3-isogeny to E', and cofactor clearing
with the endomorphism ψ (RFC 9380, §8.8.2 and Appendix G.3).
Maps an Fp element to a G1 point (EIP-2537 MAP_FP_TO_G1): the simplified
SWU map onto E1', the 11-isogeny to E, and cofactor clearing by
h_eff = 1 − x (RFC 9380, §6.6.2, §6.6.3 and §8.8.1).
Returns the multi-scalar multiplication Σ kᵢ·Pᵢ over {point, scalar}
pairs of one group.
Negates an affine point.
Returns whether an affine point lies on its curve: E (y² = x³ + 4) for a G1 point, the twist E' (y² = x³ + 4(1 + u)) for a G2 point.
Returns whether the product of e(P, Q) over pairs is 1 in GT.
Types
An element a0 + a1·u of Fp2.
@type fp() :: non_neg_integer()
An element of Fp, in [0, p).
An affine G1 point (on E) or the point at infinity.
An affine G2 point (on the twist E') or the point at infinity.
An affine point of either group.
Functions
Adds two affine points of the same group, both on the curve.
@spec fp_modulus() :: pos_integer()
Returns the base field modulus p.
Decompresses a 48-byte G1 point in the ZCash serialization used by KZG
commitments and proofs (the consensus specs' bytes_to_kzg_commitment).
The top three bits are flags: compressed (must be set), infinity, and the sign that picks the larger of y and p − y. The result is on the curve but not checked to be in G1.
@spec g1_generator() :: g1()
Returns the standard generator of G1.
@spec g2_generator() :: g2()
Returns the standard generator of G2.
Returns whether a point already known to be on its curve lies in the order-r subgroup (G1 or G2).
Instead of computing r·P (255 doublings), this uses Scott's endomorphism tests ("A note on group membership tests for G1, G2 and GT on BLS pairing-friendly curves", eprint 2021/1130, §6 and §4), whose correctness for BLS12-381 is proved in Dai, Lin, Zhao and Zhou, eprint 2022/352:
- G1: σ(P) = −[x²]P, with σ(x, y) = (β·x, y);
- G2: ψ(P) = [x]P.
Each needs one or two multiplications by the 64-bit |x|.
Maps an Fp2 element to a G2 point (EIP-2537 MAP_FP2_TO_G2): the
simplified SWU map onto E2', the 3-isogeny to E', and cofactor clearing
with the endomorphism ψ (RFC 9380, §8.8.2 and Appendix G.3).
Maps an Fp element to a G1 point (EIP-2537 MAP_FP_TO_G1): the simplified
SWU map onto E1', the 11-isogeny to E, and cofactor clearing by
h_eff = 1 − x (RFC 9380, §6.6.2, §6.6.3 and §8.8.1).
@spec msm([{point(), non_neg_integer()}]) :: point()
Returns the multi-scalar multiplication Σ kᵢ·Pᵢ over {point, scalar}
pairs of one group.
Every point must be in the order-r subgroup, so each scalar is first reduced mod r. A single term uses a width-5 NAF; several use Pippenger's bucket method.
Negates an affine point.
Returns whether an affine point lies on its curve: E (y² = x³ + 4) for a G1 point, the twist E' (y² = x³ + 4(1 + u)) for a G2 point.
Returns whether the product of e(P, Q) over pairs is 1 in GT.
Each pair is {g1, g2} of points already checked to be in G1 and G2.
Pairs with a point at infinity contribute 1. One Miller loop is shared by
every pair, followed by a single final exponentiation.