# `EEVM.Precompiles.BN256.Curve`
[🔗](https://github.com/mw2000/eevm/blob/v0.1.0/lib/eevm/precompiles/bn256/curve.ex#L1)

Arithmetic on the BN254 (alt_bn128) curve for the ecAdd, ecMul, and
ecPairing precompiles (EIP-196, EIP-197): G1 point addition and scalar
multiplication, G2 curve and subgroup checks, and the optimal ate pairing.

Field elements are plain integers in `[0, p)`, kept canonical after every
operation. The extension fields form the usual tower:

- Fp2 = Fp[i] / (i² + 1), as `{a0, a1}` = a0 + a1·i
- Fp6 = Fp2[v] / (v³ − ξ) with ξ = 9 + i, as `{c0, c1, c2}`
- Fp12 = Fp6[w] / (w² − v), as `{c0, c1}`

G1 is the curve E: y² = x³ + 3 over Fp, of prime order n. G2 lives on the
D-type sextic twist E': y² = x³ + 3/ξ over Fp2, which maps into E(Fp12) by
(x, y) ↦ (x·w², y·w³).

`pairing_check/1` runs one Miller loop shared by every pair over the NAF of
6u + 2, then a single final exponentiation, and compares the product with 1.
The structure follows arkworks' `ark-ec` BN model and the final
exponentiation follows go-ethereum's `crypto/bn256/cloudflare`.

# `fp2`

```elixir
@type fp2() :: {fp(), fp()}
```

An element a0 + a1·i of Fp2.

# `fp`

```elixir
@type fp() :: non_neg_integer()
```

An element of Fp, in `[0, p)`.

# `g1`

```elixir
@type g1() :: {fp(), fp()}
```

An affine G1 point (not the point at infinity).

# `g1_or_infinity`

```elixir
@type g1_or_infinity() :: g1() | :infinity
```

An affine G1 point or the point at infinity.

# `g2`

```elixir
@type g2() :: {fp2(), fp2()}
```

An affine point on the twist E' (not the point at infinity).

# `g1_add`

```elixir
@spec g1_add(g1_or_infinity(), g1_or_infinity()) :: g1_or_infinity()
```

Adds two G1 points (ecAdd), both on the curve.

# `g1_mul`

```elixir
@spec g1_mul(g1_or_infinity(), non_neg_integer()) :: g1_or_infinity()
```

Multiplies a G1 point on the curve by a scalar (ecMul).

E(Fp) has prime order n, so k·P = (k mod n)·P for every point on the curve,
and the scalar is reduced first. The product uses a width-5 NAF over a table
of odd multiples of P, all in Jacobian coordinates, with one inversion at
the end to return an affine point.

# `g1_on_curve?`

```elixir
@spec g1_on_curve?(g1()) :: boolean()
```

Returns whether `point` lies on E: y² = x³ + 3.

# `g2_in_subgroup?`

```elixir
@spec g2_in_subgroup?(g2()) :: boolean()
```

Returns whether a point on the twist lies in G2, the order-n subgroup.

EIP-197 requires it; unlike G1, the twist also has points of other orders.
Instead of computing n·Q (254 doublings), this uses the endomorphism test
from Dai, Lin, Zhao and Zhou, "Fast subgroup membership testings for G1, G2
and GT on pairing-friendly curves" (eprint 2022/348, §3 and §5.1), also used
by gnark-crypto: Q ∈ G2 ⟺ [u + 1]Q + ψ([u]Q) + ψ²([u]Q) = ψ³([2u]Q). That
needs one 63-bit multiplication by u.

The test accepts exactly the kernel of a group endomorphism. G2 is in the
kernel; the rest of the twist group is cyclic of square-free order
h = 2p − n = 10069 · 5864401 · 1875725156269 · q₄ (q₄ prime), so the test is
sound if it rejects one point of each of those prime orders. The unit tests
check exactly that.

# `g2_on_curve?`

```elixir
@spec g2_on_curve?(g2()) :: boolean()
```

Returns whether `point` lies on the twist E': y² = x³ + 3/ξ.

# `pairing_check`

```elixir
@spec pairing_check([{g1(), g2()}]) :: boolean()
```

Returns whether the product of e(P, Q) over `pairs` is 1 in GT.

Each pair is `{g1, g2}`: an affine point of G1 and an affine point of G2,
both already validated. Pairs with a point at infinity contribute 1, so
callers leave them out.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
