Skip to main content

G2 Operations

G2 is the extension field elliptic curve group used for BLS public keys. Points are 96 bytes compressed or 192 bytes uncompressed.

G2 Curve Equation

y² = x³ + 4(1 + i) over Fp2
Extension Field: Fp2 = Fp[i] / (i² + 1) Group Order: r (same as G1) Cofactor: h2 = 0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5

Point Formats

Uncompressed (192 bytes, padded to 256 for precompiles)

| x.c0 | x.c1 | y.c0 | y.c1 |
|  48  |  48  |  48  |  48  |
| (64) | (64) | (64) | (64) |
Each coordinate is Fp2 element: a + bi where a, b ∈ Fp

Compressed (96 bytes)

| x.c1 (with flags) | x.c0 |
|     48 bytes      | 48 bytes |

Operations

Point Addition

import { bls12_381 } from '@tevm/voltaire/crypto';

const p1 = new Uint8Array(256);
const p2 = new Uint8Array(256);

const input = new Uint8Array(512);
input.set(p1, 0);
input.set(p2, 256);

const output = new Uint8Array(256);
await bls12_381.g2Add(input, output);
Gas Cost: 800 (EIP-2537) Time: ~25 μs

Scalar Multiplication

const point = new Uint8Array(256);
const scalar = Bytes32();

const input = new Uint8Array(288);
input.set(point, 0);
input.set(scalar, 256);

const output = new Uint8Array(256);
await bls12_381.g2Mul(input, output);
Gas Cost: 45,000 (EIP-2537) Time: ~200 μs

Multi-Scalar Multiplication

const n = 50;
const input = new Uint8Array(288 * n);

for (let i = 0; i < n; i++) {
  const offset = 288 * i;
  input.set(publicKeys[i], offset);
  input.set(scalars[i], offset + 256);
}

const output = new Uint8Array(256);
await bls12_381.g2Msm(input, output);
Use Case: Aggregate validator public keys

Subgroup Membership

Critical: G2 has large cofactor - must verify subgroup membership! Attack: Invalid curve attack if subgroup not checked BLST automatically validates:
  • Point on curve
  • In prime-order subgroup
  • Coordinates in field
// Will throw if point not in subgroup
await bls12_381.g2Add(input, output);

Public Key Aggregation

async function aggregatePublicKeys(
  publicKeys: Uint8Array[]
): Promise<Uint8Array> {
  let aggregated = publicKeys[0];

  for (let i = 1; i < publicKeys.length; i++) {
    const input = new Uint8Array(512);
    input.set(aggregated, 0);
    input.set(publicKeys[i], 256);

    const output = new Uint8Array(256);
    await bls12_381.g2Add(input, output);
    aggregated = output;
  }

  return aggregated;
}
Ethereum: Aggregate 512 sync committee public keys

Performance

Native (BLST):
  • Addition: ~25 μs
  • Scalar mul: ~200 μs
  • MSM (50): ~6 ms
  • MSM (512): ~50 ms
Optimization: MSM much faster than individual multiplications for validator key aggregation