> ## 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.

# 0x0B BLS12-381 G1 Add

> BLS12-381 G1 elliptic curve 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:** `0x000000000000000000000000000000000000000b`
**Introduced:** Prague (EIP-2537)
**EIP:** [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537)

The BLS12-381 G1 Add precompile performs elliptic curve point addition on the BLS12-381 curve's G1 group. It takes two G1 points and returns their sum. This is essential for BLS signature verification, consensus protocols, and advanced cryptographic applications.

EIP-2537 introduces BLS12-381 curve operations to Ethereum, enabling efficient BLS signatures used in Ethereum 2.0 consensus and other cryptographic protocols requiring pairing-friendly curves.

The BLS12-381 curve is a pairing-friendly elliptic curve designed for zkSNARKs and signature aggregation, offering 128-bit security with efficient pairing operations.

## Gas Cost

**Fixed:** `500` gas

## Input Format

```
Offset | Length | Description
-------|--------|-------------
0      | 64     | x1 (first point x-coordinate, big-endian, left-padded)
64     | 64     | y1 (first point y-coordinate, big-endian, left-padded)
128    | 64     | x2 (second point x-coordinate, big-endian, left-padded)
192    | 64     | y2 (second point y-coordinate, big-endian, left-padded)
```

Total input length: 256 bytes (exactly)

Points must satisfy the curve equation: `y^2 = x^3 + 4` over the BLS12-381 base field (Fp).
Point at infinity is represented as all zeros (128 bytes of zeros for each point).

## Output Format

```
Offset | Length | Description
-------|--------|-------------
0      | 64     | x (result point x-coordinate, big-endian, left-padded)
64     | 64     | y (result point y-coordinate, big-endian, left-padded)
```

Total output length: 128 bytes

## TypeScript Example

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

// BLS12-381 G1 generator point (48 bytes, left-padded to 64)
const g1_x = Bytes64('0x000000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb');
const g1_y = Bytes64('0x0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1');

// Add generator point to itself: G + G = 2G
const input = new Uint8Array(256);
input.set(g1_x, 0);
input.set(g1_y, 64);
input.set(g1_x, 128);
input.set(g1_y, 192);

const result = execute(
  PrecompileAddress.BLS12_G1_ADD,
  input,
  1000n,
  Hardfork.PRAGUE
);

if (result.success) {
  const resultX = result.output.slice(0, 64);
  const resultY = result.output.slice(64, 128);
  console.log('Result: 2*G');
  console.log('Gas used:', result.gasUsed); // 500
} else {
  console.error('Error:', result.error);
}
```

## Zig Example

```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();

    // BLS12-381 G1 generator coordinates (48 bytes, padded to 64)
    const g1_x = [_]u8{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x17, 0xf1, 0xd3, 0xa7, 0x31, 0x97, 0xd7, 0x94, 0x26, 0x95, 0x63, 0x8c, 0x4f, 0xa9, 0xac, 0x0f,
        0xc3, 0x68, 0x8c, 0x4f, 0x97, 0x74, 0xb9, 0x05, 0xa1, 0x4e, 0x3a, 0x3f, 0x17, 0x1b, 0xac, 0x58,
        0x6c, 0x55, 0xe8, 0x3f, 0xf9, 0x7a, 0x1a, 0xef, 0xfb, 0x3a, 0xf0, 0x0a, 0xdb, 0x22, 0xc6, 0xbb,
    };
    const g1_y = [_]u8{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x08, 0xb3, 0xf4, 0x81, 0xe3, 0xaa, 0xa0, 0xf1, 0xa0, 0x9e, 0x30, 0xed, 0x74, 0x1d, 0x8a, 0xe4,
        0xfc, 0xf5, 0xe0, 0x95, 0xd5, 0xd0, 0x0a, 0xf6, 0x00, 0xdb, 0x18, 0xcb, 0x2c, 0x04, 0xb3, 0xed,
        0xd0, 0x3c, 0xc7, 0x44, 0xa2, 0x88, 0x8a, 0xe4, 0x0c, 0xaa, 0x23, 0x29, 0x46, 0xc5, 0xe7, 0xe1,
    };

    // Construct input: G + G
    var input: [256]u8 = [_]u8{0} ** 256;
    @memcpy(input[0..64], &g1_x);
    @memcpy(input[64..128], &g1_y);
    @memcpy(input[128..192], &g1_x);
    @memcpy(input[192..256], &g1_y);

    const result = try precompiles.bls12_g1_add.execute(allocator, &input, 1000);
    defer result.deinit(allocator);

    std.debug.print("Result: 2*G\n", .{});
    std.debug.print("Gas used: {}\n", .{result.gas_used});
}
```

## Error Conditions

* **Out of gas:** gasLimit \< 500
* **Invalid input length:** input.len != 256
* **Invalid point:** Point coordinates don't satisfy curve equation y² = x³ + 4
* **Point not in subgroup:** Point not in correct subgroup (fails validation)
* **Coordinate out of range:** x or y >= field modulus

Invalid inputs cause precompile to return `error.InvalidPoint`.

## Use Cases

* **BLS signature verification:** Aggregating and verifying BLS signatures
* **Ethereum 2.0 consensus:** Validator signature aggregation
* **zkSNARKs on BLS12-381:** Proof systems using BLS12-381 curve
* **Distributed key generation:** Threshold cryptography protocols
* **Verifiable delay functions:** VDFs using pairings
* **Privacy protocols:** zk-Rollups and privacy-preserving systems

## Implementation Details

* **Zig:** Uses blst library (C) via crypto module for G1 operations
* **TypeScript:** Uses @noble/curves bls12-381 implementation
* **Curve:** BLS12-381 with embedding degree 12
* **Field modulus (p):** 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
* **Group order (r):** 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001

## BLS12-381 G1 Parameters

* **Curve equation:** y² = x³ + 4
* **Base field:** Fp (381-bit prime)
* **Coordinate size:** 48 bytes (padded to 64 bytes in precompile encoding)
* **Generator G1 x:** 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb
* **Generator G1 y:** 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1
* **Point at infinity:** All zeros (128 bytes)

## Point Addition Rules

* **P + O = P** (identity element)
* **O + P = P** (identity is commutative)
* **P + P = 2P** (point doubling)
* **P + (-P) = O** (inverse gives infinity)
* General addition uses elliptic curve group law

## Security Considerations

* All coordinates must be validated to be in field and on curve
* Points must be checked for subgroup membership
* Implementation uses constant-time operations where possible
* Uses battle-tested blst library for security-critical operations

## Performance Notes

* Fixed gas cost makes G1 addition predictable
* More efficient than generic elliptic curve operations
* Hardware acceleration available on some platforms via blst
* Point validation adds overhead but is necessary for security

## Related

* [Precompile: BLS12-381 G1 Mul](/evm/precompiles/bls12-g1-mul)
* [Precompile: BLS12-381 G1 MSM](/evm/precompiles/bls12-g1-msm)
* [Precompile: BLS12-381 Pairing](/evm/precompiles/bls12-pairing)
* [EIP-2537: Precompiled Contracts for BLS12-381 Curve Operations](https://eips.ethereum.org/EIPS/eip-2537)
* [BLS12-381 Specification](https://hackmd.io/@benjaminion/bls12-381)
