[ERC2537] BLS12-381プリコンパイルの仕組みを理解しよう！

# はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、Ethereum上でより安全性の高いBLS12-381曲線を使った暗号演算を高速かつ低ガスで実行するための7種類の専用プリコンパイルを提案している**ERC2537**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-2537

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

# 概要

**ERC2537**は、BLS12-381というペアリングフレンドリーな楕円曲線に対して、効率的な演算機能を提供するプリコンパイル（precompile）を導入している提案です。
主な目的は、BLS署名の検証に必要な楕円曲線演算やマルチスカラ乗算（複数のスカラーと点の積を同時に計算する操作）を、高速かつ低コストで実行できるようにすることです。

特に、BLS署名では複数の公開鍵や署名を集約（アグリゲーション）する際に、多くの曲線演算が必要となるため、これらを効率化することで現実的な運用が可能になります。

:::note info
### MSMとは何か？

MSM（Multi-Scalar Multiplication、マルチスカラ乗算）とは、以下のような形式の演算をまとめて効率的に計算する技術です。

```
r = s₁ * P₁ + s₂ * P₂ + ... + sₖ * Pₖ
```

* `P₁, P₂, ..., Pₖ` は楕円曲線上の点（G1またはG2の点）
* `s₁, s₂, ..., sₖ` はスカラー（整数値）
* `*` は楕円曲線上のスカラー倍演算（点を整数回「足す」操作）
* `+` は点同士の加算

この演算はBLS署名の検証やゼロ知識証明で頻繁に現れます。
単純に逐次的に計算することもできますが、効率的なアルゴリズム（例：Pippenger法）を使うとまとめて高速に計算できるため、Ethereumのプリコンパイルで専用のMSM処理が提供されています。

* BLS署名では、複数の署名や公開鍵を1つにまとめて検証する「署名集約（Aggregation）」が行われます。
* その際、署名者の数に応じた多数のスカラー×点の積が必要となるため、MSMを使えば大幅にガスコストを削減できます。
* 特に分散型検証やZK系のプロトコルで重要です。

```
MSM演算の流れ：

 [点P₁]    [点P₂]    [点P₃]       ← 楕円曲線上の点（公開鍵など）
   |         |         |
 [×s₁]     [×s₂]     [×s₃]         ← 各点に対してスカラー倍（整数の乗算）
   |         |         |
   +----+----+-----> 合計（加算）
                 ↓
               出力点（結果）
```

このように、MSMは「たくさんの点×スカラーをまとめて計算し、1つの点を出す」操作です。これを1つずつ計算するより圧倒的に効率的なので、ブロックチェーンのようなリソース制限のある環境では特に重要です。
:::

# 動機

現行のEthereumにはBN254曲線（別名：Alt\_bn128）に対するペアリング演算のプリコンパイルがありますが、これは約80ビットの暗号強度しか持っておらず、将来的な耐量子性や長期的な安全性に不安があります。

BLS12-381曲線は、より高い暗号強度（120ビット以上）を提供することで、より安全な署名スキームを実現します。
これにより、ゼロ知識証明（ZKP）やBLS署名ベースの認証方式を、安全かつ効率的にブロックチェーン上で活用できるようになります。

また、このプリコンパイルは複雑な署名アグリゲーション処理においてもガスコストを抑え、スケーラビリティの高いアプリケーションの構築を可能にします。

# 仕様

この仕様は、EthereumにおけるBLS12-381曲線の操作を効率的に実行するための7つの新しいプリコンパイル（組み込み処理）を定義しています。
BLS署名の検証や集約に必要な基本演算やマルチスカラ乗算（MSM）、ペアリング演算、フィールドから曲線へのマッピングなどをサポートします。

## プリコンパイル一覧と機能

以下のアドレスにそれぞれの操作が割り当てられています。

* `0x0b`
    * G1点の加算（BLS12_G1ADD）
* `0x0c`
    * G1でのMSM（BLS12_G1MSM）
* `0x0d`
    * G2点の加算（BLS12_G2ADD）
* `0x0e`
    * G2でのMSM（BLS12_G2MSM）
* `0x0f`
    * ペアリング演算（BLS12_PAIRING_CHECK）
* `0x10`
    * FpからG1へのマッピング（BLS12_MAP_FP_TO_G1）
* `0x11`
    * Fp2からG2へのマッピング（BLS12_MAP_FP2_TO_G2）

## 楕円曲線とフィールドの定義

* 曲線式（G1）
    * `Y^2 = X^3 + B`（mod p）、A=0
* 基本フィールド（Fp）
    * p = `0x1a0111...aaab`（381ビット）
* 拡張フィールド（Fp2）
    * Fp2 = Fp\[X]/(X² - nr2)

G1はFp上、G2はFp2上に定義された曲線で、署名検証時に重要な役割を果たします。

## 入力・出力のエンコーディング仕様

* **Fp要素**
    * 64バイト（BigEndian、上位16バイトは0）
* **Fp2要素**
    * 128バイト（Fp要素2つを連結）
* **G1点**
    * x, yのFp値を連結して128バイト
* **G2点**
    * x, yのFp2値を連結して256バイト
* **スカラー値**
    * 32バイトのBigEndian整数

(0,0)は実際の曲線上の点ではないが、慣習的に無限遠点（何もない場所にある特別な点）として使用。

## 各操作のABIとエラー条件

### G1加算（BLS12\_G1ADD）

* 入力: G1点2つ（256バイト）
* 出力: 加算後のG1点（128バイト）
* エラー: 点が無効、入力長さ不正など

### G1 MSM（BLS12\_G1MSM）

* 入力: G1点＋スカラーのペアk個（160kバイト）
* 出力: MSM結果のG1点（128バイト）
* エラー: 点が無効、サブグループ外、長さ不正など

### G2加算（BLS12\_G2ADD）

* 入力: G2点2つ（512バイト）
* 出力: 加算後のG2点（256バイト）

### G2 MSM（BLS12\_G2MSM）

* 入力: G2点＋スカラーのペアk個（288kバイト）
* 出力: MSM結果のG2点（256バイト）

### ペアリング検証（BLS12\_PAIRING\_CHECK）

* 入力: G1とG2のペアk個（384kバイト）
* 出力: 成否（32バイト、末尾が0x00または0x01）
* 条件: 全ての点はサブグループqに属する必要あり

### Fp→G1マッピング

* 入力: Fp要素（64バイト）
* 出力: G1点（128バイト）

### Fp2→G2マッピング

* 入力: Fp2要素（128バイト）
* 出力: G2点（256バイト）

## ガスコスト（目安）

| 操作      | ガス                  |
| ------- | ------------------- |
| G1加算    | 375                 |
| G1乗算    | 12000               |
| G2加算    | 600                 |
| G2乗算    | 22500               |
| Fp→G1   | 5500                |
| Fp2→G2  | 23800               |
| ペアリング検証 | `32600 * k + 37700` |
| G1 MSM  | 割引付き計算式による          |
| G2 MSM  | 割引付き計算式による          |

MSMはPippengerアルゴリズムによる高速処理が前提で、入力数が増えるとガス割引が適用されます。

## 入力の長さとエラー処理

* MSMやペアリングなど、可変長入力を取る操作では、入力長が適切でなければエラーを返す必要があります。
* 長さがペア単位で割り切れない場合でも、ガスは消費され、実行時にはエラーが返されます。

## エラー時の挙動

全てのプリコンパイルにおいて、エラーが発生した場合は供給されたガス全てが消費（burn）されます。
これはEthereumの既存のプリコンパイルと同様の設計です。

# 補足

## MSMを独立した呼び出しにした理由

MSM（マルチスカラ乗算）を専用のプリコンパイルとして分離した最大の理由は、ガスコストと実行時間の大幅な削減です。
具体的には以下の2点にです。

* **Pippenger法**という効率的なアルゴリズムを使うことで、100個の `(点, スカラー)` ペアに対する乗算・加算をまとめて計算できます。
* Ethereumにおける `CALL` 処理は非常に高コストであり、単純に100回のスカラー倍＋99回の加算を個別にプリコンパイルで実行した場合、約138,600ガスの無駄が発生する試算があります。

このように、MSM専用のプリコンパイルは処理速度とガス効率の両面で優れているため、独立した呼び出しとして設計されました。

## 乗算専用プリコンパイルを設けない理由

`点 × スカラー` のような単独のスカラー倍演算（MUL）は、MSMの特殊ケース（k=1）として処理できます。
そのため、以下の設計方針が採用されています。

* 専用の乗算（MUL）プリコンパイルは定義されていません。
* 代わりに、MSMの入力長が「1ペア分（k=1）」の場合は、複雑なアルゴリズムを回避して単純な乗算処理にフォールバックするようになっています。

これにより、ABI（入力フォーマット）を1つに統一しながら*乗算のような軽量処理にも対応可能な柔軟性が確保されています。
これは仕様の簡素化と実装コストの低減にもつながります。

# 互換性

## サブグループチェックの必須化

MSM（マルチスカラ乗算）およびペアリング演算においては、使用される点が正しいサブグループに属していることを検証（サブグループチェック）する必要があります。

サブグループとは、楕円曲線上の点集合のうち、安全な暗号操作に使用すべき正しい集合のことです。
間違ったサブグループの点を使うと、署名偽造や計算不正が可能になる可能性があります。

プリコンパイル実装は、別ドキュメントで定義された最適化されたチェック方法（効率のよい検証手法）の使用が推奨されており、チェックに失敗した場合は*ラーを返す必要があります。

## エンドモルフィズム最適化との関係

エンドモルフィズムによる高速化（endomorphism acceleration）を用いる場合、正しいサブグループの点であることが前提条件となるため、サブグループチェックは必須となります。エンドモルフィズムとは、特定の変換を用いて演算を高速化するテクニックです。

:::note info
### エンドモルフィズムとは？

**エンドモルフィズム（endomorphism）**とは、楕円曲線の構造を保ったまま自己写像（自分自身への変換）を行う関数のことです。
簡単に言えば、楕円曲線上の点を別の点に写すが、その写し方が楕円曲線の加算ルールと整合しているという性質を持ちます。

この性質をうまく使うと、スカラー乗算の高速化が可能になります。

### スカラー乗算の高速化とエンドモルフィズム

楕円曲線暗号では、以下のようなスカラー乗算が非常に頻繁に使われます。

```
Q = k * P
```

これは、点 `P` を `k` 回加算していく操作です。
大きな `k` に対しては非常に重くなるため、これを高速化したいというモチベーションがあります。

エンドモルフィズムを利用することで、`k` を複数の小さな係数に分解し、それぞれを並列計算できるようになります。

### 例：Gallant–Lambert–Vanstone（GLV）法

GLV法では、以下のようにスカラー `k` を分解します。

```
k * P = k₁ * P + k₂ * φ(P)
```

ここで `φ(P)` はエンドモルフィズムで、元の点 `P` を別の点に変換します。
ただし、曲線の加法構造を維持しているため、演算結果は正確です。
このようにすれば、元のスカラー乗算をより短いスカラー2つの乗算に分割して並列化できるため、高速化につながります。

### BLS12-381 における応用

BLS12-381などのペアリング曲線では、スカラー乗算を高速化するために効率の良いエンドモルフィズムが存在します。
ただし、これを安全に使うには、使用する点が正しいサブグループに属している必要があります。
:::

## フィールドから曲線へのマッピング

FpやFp2の要素を曲線の点（G1, G2）にマッピングする方法としては、SWU（Shallue–van de Woestijne–Ulas）法が使用されます。具体的なアルゴリズムとパラメータは、別の文書で定義されています。

このマッピングはBLS署名などで、ハッシュ値を曲線の点に変換する場面で使用されます。
ここでは実装の互換性よりも正確かつ安全な点変換が行われることが重視されます。

# セキュリティ

## 仕様を順守する意義

提案されているプリコンパイルは、BLS12-381曲線での演算を厳密に仕様どおり実装するかぎり*ネットワーク全体のコンセンサスや暗号強度に影響を与えません。
旧 BN254 プリコンパイルでは `80` ビット相当の安全性しか得られませんでしたが、**ERC2537**では `120` ビット超の安全性が確保できます。

## 定数時間実装（constant-time）の扱い

**定数時間実装**とは、入力値の大小や秘密情報にかかわらず処理時間が一定になるように実装する手法で、タイミング攻撃（実行時間の揺らぎから秘密情報を推測する攻撃）を防ぐ効果があります。
**ERC2537**では **「すべての処理を定数時間で実装することは必須ではない」と明記されています。
BLS12-381ではサイドチャネル耐性を高めるために定数時間実装が望ましい場面がありますが、必須条件にすると実装負荷が高まるため、仕様レベルでの義務化は行われていません。
実装者は、利用シーン（秘密鍵を扱うかどうか、オフチェーンでの前処理の有無など）を踏まえ、必要に応じて定数時間化を検討することが推奨されます。

## 実装時のベストプラクティス

* **サブグループチェックの徹底**
  仕様どおりにサブグループチェックを実施し、誤った点が演算に使われることを防ぎます。
* **入力検証の厳格化**
  不正な長さや範囲外の値が与えられた場合はエラーを返し、ガスをBurnして処理を中断します。
* **ライブラリ選定**
  オープンソース実装を利用する場合は、タイミング耐性や形式検証の有無など、セキュリティレビューが十分に行われているかを確認します。

# 引用

Alex Vlasov (@shamatar), Kelly Olson (@ineffectualproperty), Alex Stokes (@ralexstokes), Antonio Sanso (@asanso), "EIP-2537: Precompile for BLS12-381 curve operations," Ethereum Improvement Proposals, no. 2537, February 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2537.

# 最後に

今回は「Ethereum上でより安全性の高いBLS12-381曲線を使った暗号演算を高速かつ低ガスで実行するための7種類の専用プリコンパイルを提案している**ERC2537**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4