> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# 0x0e BLS12-381 G2 Add

> BLS12-381 G2 point addition

<Warning>
  **This page is a placeholder.** All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.
</Warning>

## Overview

**Address:** `0x000000000000000000000000000000000000000e`
**Introduced:** Prague (EIP-2537)
**EIP:** [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537)

The BLS12-381 G2 Add precompile performs point addition on the BLS12-381 curve's G2 group. It adds two G2 points together, computing `point1 + point2`. This operation is essential for BLS signature aggregation and advanced cryptographic protocols requiring operations over extension fields.

BLS12-381 provides 128 bits of security (compared to BN254's 80 bits) and is used in Ethereum 2.0's consensus layer for validator signature verification.

## Gas Cost

**Fixed:** `800` gas

## G2 vs G1

**G2 points** are defined over the extension field Fp2 (quadratic extension of the base field):

* **G1 points:** 128 bytes (64 bytes per coordinate, 2 coordinates)
* **G2 points:** 256 bytes (128 bytes per coordinate, 2 coordinates)
* **Field representation:** Each G2 coordinate is an Fp2 element (c0 + c1\*u)
* **Computational cost:** G2 operations are more expensive than G1 due to extension field arithmetic

## Input Format

```
Offset | Length | Description
-------|--------|-------------
0      | 64     | x.c0 (point1 x-coordinate c0 component, big-endian)
64     | 64     | x.c1 (point1 x-coordinate c1 component, big-endian)
128    | 64     | y.c0 (point1 y-coordinate c0 component, big-endian)
192    | 64     | y.c1 (point1 y-coordinate c1 component, big-endian)
256    | 64     | x.c0 (point2 x-coordinate c0 component, big-endian)
320    | 64     | x.c1 (point2 x-coordinate c1 component, big-endian)
384    | 64     | y.c0 (point2 y-coordinate c0 component, big-endian)
448    | 64     | y.c1 (point2 y-coordinate c1 component, big-endian)
```

Total input length: 512 bytes (256 bytes per G2 point)

Each G2 point coordinate is an Fp2 element represented as: `c0 + c1*u` where u is the extension field element.

Points must satisfy the G2 curve equation: `y^2 = x^3 + 4(1 + u)` over Fp2.

## Output Format

```
Offset | Length | Description
-------|--------|-------------
0      | 64     | x.c0 (result point x-coordinate c0 component, big-endian)
64     | 64     | x.c1 (result point x-coordinate c1 component, big-endian)
128    | 64     | y.c0 (result point y-coordinate c0 component, big-endian)
192    | 64     | y.c1 (result point y-coordinate c1 component, big-endian)
```

Total output length: 256 bytes

## Usage Example

### TypeScript

```typescript theme={null}
import { execute, PrecompileAddress } from '@tevm/voltaire/precompiles';
import { Hardfork } from '@tevm/voltaire/primitives/Hardfork';

// Add two G2 points (each 256 bytes: 4x 64-byte Fp2 components)
// Point at infinity for both (valid operation: O + O = O)
const point1 = new Uint8Array(256); // All zeros = point at infinity
const point2 = new Uint8Array(256); // All zeros = point at infinity

const input = new Uint8Array(512);
input.set(point1, 0);
input.set(point2, 256);

const result = execute(
  PrecompileAddress.BLS12_G2_ADD,
  input,
  10000n,
  Hardfork.PRAGUE
);

if (result.success) {
  const resultPoint = result.output; // 256 bytes
  const xc0 = result.output.slice(0, 64);
  const xc1 = result.output.slice(64, 128);
  const yc0 = result.output.slice(128, 192);
  const yc1 = result.output.slice(192, 256);
  console.log('Result G2 point:', { xc0, xc1, yc0, yc1 });
  console.log('Gas used:', result.gasUsed); // 800
} else {
  console.error('Error:', result.error);
}
```

### Zig

```zig theme={null}
const std = @import("std");
const precompiles = @import("precompiles");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Create input: two G2 points (512 bytes)
    var input = [_]u8{0} ** 512;
    // ... populate input with G2 point coordinates

    // Execute G2 addition
    const result = try precompiles.bls12_g2_add.execute(
        allocator,
        &input,
        10000
    );
    defer result.deinit(allocator);

    std.debug.print("Gas used: {}\n", .{result.gas_used});
    std.debug.print("Output length: {}\n", .{result.output.len}); // 256
}
```

## Error Conditions

* **Out of gas:** gasLimit \< 800
* **Invalid input length:** input.len != 512
* **Point not on curve:** coordinates don't satisfy G2 curve equation
* **Invalid field element:** coordinate component >= field modulus
* **Invalid encoding:** malformed Fp2 element representation

## Use Cases

* **BLS signature aggregation:** Combine multiple G2 signatures
* **Multi-signature schemes:** Aggregate public keys or signatures
* **Threshold cryptography:** Combine signature shares
* **Proof aggregation:** Combine multiple proofs efficiently
* **Ethereum 2.0 consensus:** Validator signature operations

## Implementation Details

* **Zig:** Uses BLST library via crypto module
* **TypeScript:** Wraps @noble/curves bls12-381 G2 operations
* **Algorithm:** Projective coordinates for efficiency
* **Security:** 128-bit security level (vs BN254's 80-bit)
* **Constant-time:** Implementation resistant to timing attacks

## Special Cases

* **Point at infinity:** All zeros (256 bytes) represents identity element
* **Identity + P:** Returns P
* **P + (-P):** Returns point at infinity
* **Identity + identity:** Returns identity

The point at infinity is represented as 256 bytes of zeros and acts as the identity element for G2 addition.

## Extension Field Arithmetic

G2 points use the quadratic extension field Fp2:

* **Field elements:** `a = a.c0 + a.c1*u` where u^2 + 1 = 0
* **Addition:** `(a + b) = (a.c0 + b.c0) + (a.c1 + b.c1)*u`
* **Multiplication:** More complex due to extension field rules
* **Encoding:** Each component (c0, c1) is 64 bytes big-endian

## Gas Comparison

| Operation       | G1 Gas   | G2 Gas   | Ratio |
| --------------- | -------- | -------- | ----- |
| Addition        | 500      | 800      | 1.6x  |
| Multiplication  | 12,000   | 45,000   | 3.75x |
| MSM (per point) | \~12,000 | \~45,000 | 3.75x |

G2 operations are more expensive due to:

* Extension field arithmetic (Fp2 vs Fp)
* Larger point representation (256 vs 128 bytes)
* More complex coordinate operations

## Security Considerations

BLS12-381 advantages over BN254:

* **Security level:** 128 bits vs 80 bits
* **Future-proof:** Resistant to known attacks on pairing curves
* **Standardization:** Used in Ethereum 2.0, Zcash, Filecoin
* **Performance:** Efficient pairing computation

## Performance Notes

* G2 addition is \~60% more expensive than G1 addition (800 vs 500 gas)
* Prefer batching operations when possible
* Consider using MSM for multiple operations with same points
* G2 operations required for signature verification in BLS schemes

## Related

* [Precompile: BLS12-381 G2 Mul](/evm/precompiles/bls12-g2-mul)
* [Precompile: BLS12-381 G2 MSM](/evm/precompiles/bls12-g2-msm)
* [Precompile: BLS12-381 G1 Add](/evm/precompiles/bls12-g1-add)
* [Precompile: BLS12-381 Pairing](/evm/precompiles/bls12-pairing)
* [Crypto: BLS12-381](/crypto/bls12-381)
* [EIP-2537: Precompile for BLS12-381 curve operations](https://eips.ethereum.org/EIPS/eip-2537)
