# [ACP204] C-ChainにP-256検証を行うプリコンパイルを追加する仕組みを理解しよう！

> ACP204は、AvalancheのC-Chainにsecp256r1（P-256）楕円曲線の署名検証を行うプリコンパイルコントラクト（precompiled contract）を導入するものです。

- URL: https://cardene.dev/articles/e874823f8a61aba5dc43
- 公開日: 2025-09-25
- 更新日: 2025-09-25
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、AvalancheのC-ChainにP-256（secp256r1）署名検証のプリコンパイルを追加し、WebAuthnや端末内セキュリティで生成された署名を低ガスでネイティブ検証できる仕組みを提案している**ACP204**についてまとめていきます！

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

https://github.com/avalanche-foundation/ACPs/blob/main/ACPs/204-precompile-secp256r1/README.md

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

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

## 概要

**ACP204**は、AvalancheのC-Chainに**secp256r1（P-256）**楕円曲線の署名検証を行うプリコンパイルコントラクト（precompiled contract）を導入するものです。
プリコンパイルコントラクトとは、EVM内の特定アドレスに配置し、Solidityで書くと計算量が大きくなりがちな暗号処理などをネイティブ実装で高速・低ガスに実行できる仕組みのことです。
**ACP204**で提案されているプリコンパイルはアドレス`0x0000000000000000000000000000000000000100`に配置され、Ethereumの**EIP7951**が規定するP-256検証の仕様に合わせます。
これにより、生体認証（FaceID/TouchID）やWebAuthn、Passkeys、デバイス内セキュアハードウェアによる署名を、そのままC-Chain上でネイティブに検証できるようになり、ガス効率が大幅に改善します。
**EIP7951**は、既存の**RIP7212**（L2で広く採用されてきたP-256プリコンパイル）と同一アドレス（0x…0100）・互換インターフェースを前提としており、相互運用性と将来の拡張性を確保しています。

## 動機

**secp256r1（P-256）**は、AppleのSecureEnclaveやAndroidKeystore、FIDO2/WebAuthn、Passkeysなど現代のデバイスセキュリティ標準でデフォルトとして広く使われています。
一方、現在のEVM（AvalancheC-Chainを含む）がネイティブに持つ署名検証は**secp256k1（`ecrecover`）**のみであるため、P-256署名を検証したい開発者はSolidity実装の検証コントラクトに頼らざるを得ず、1回の検証あたり約20万〜33万gasと高コストになっていました。
**ACP204**で提案されているプリコンパイルを採用すれば、P-256署名検証をEVMネイティブ処理として実行できるため、ガスコストを下げて、WebAuthn/Passkeysなどデバイス署名ベースのUX（パスワードレス・生体認証など）をスマートコントラクトで実用的なコストに引き下げられます。
結果として、アカウント抽象化（AA）や多要素認証、鍵管理の単純化といった設計が現実的になり、Avalancheエコシステム全体での採用・連携が進みます。

#### エンタープライズおよび機関利用

企業や機関がAvalancheを採用するにあたり、今回の改善は以下のような効果をもたらします。

| 観点 | 内容 |
| --- | ---- |
| オンボーディングの容易さ | 企業はすでに利用している生体認証や端末認証の仕組みをそのまま活用でき、シードフレーズやハードウェアウォレットの管理負担を避けられる |
| 規制対応 | 機関は既に承認されているデバイスセキュリティ基盤やID管理システムを利用でき、コンプライアンス要件に沿った運用が可能になる |
| コスト最適化 | ガス消費が従来の200k〜330kから約6,900gasへ削減され、検証コストが大幅に下がることで、大規模な業務システムやエンタープライズ向けアプリケーションでも経済的に利用できる |

従来に比べておよそ50倍以上のガス削減効果が得られるため、これまでコストの観点から実用が難しかったユースケースでも十分に導入可能になります。
しかも、端末が持つ既存のセキュリティ特性を維持できるため、安全性と利便性を両立できます。

#### エコシステム全体での一貫性

さらに、このプリコンパイルを**RIP7212**で定義されたものと同じアドレス（`0x000...0100`）に配置することで、他のエコシステムとアドレスの互換性が保たれます。
これにより、既に開発済みのライブラリやツールをAvalancheでも変更せずに利用でき、異なるネットワーク間での相互運用性も確保されます。

## 仕様

**ACP204**では、Avalancheにおいて**EIP7951**で定義されている**secp256r1**署名検証用プリコンパイルコントラクトを実装します。
仕様は**EIP7951**と完全に一致し、C-Chain上ではアドレス`0x0000000000000000000000000000000000000100`に配置されます。
これにより、AvalancheでもEthereumと同じ形式でP-256署名の検証が可能になり、相互運用性が確保されます。

#### コア機能

このプリコンパイルドコントラクトの処理内容は、以下の通りです。

| 項目 | 内容 |
| --- | ---- |
| 入力 | 合計160バイト。構成は「**メッセージハッシュ**」、「**署名のrとs**」「**公開鍵のx座標とy座標**」 |
| 出力 | 検証成功時は32バイト（値は`0x...01`）、失敗時はデータなし |
| ガスコスト | 6,900 gas（EIP-7951でのベンチマーク結果に基づく） |
| 検証規格 | NIST FIPS 186-3（米国標準規格）に準拠した完全な署名検証 |

入力は署名検証に必要な基本要素であるメッセージのハッシュ値・署名の2つの成分（rとs）・公開鍵の座標（xとy）を順番に並べたもので、合計で160バイトになります。
出力は非常にシンプルで、成功なら32バイトの固定値（`0x...01`）、失敗時は空データとなります。

#### アクティベーション

このプリコンパイルドコントラクトは、Avalancheの次回ネットワークアップグレードに合わせて有効化される予定です。
さらに、Avalancheの個別L1チェーンやサブネットも、それぞれのクライアントソフトウェアを更新することで、この機能を独自に取り入れることができます。
つまり、C-Chainだけでなく各サブネットの設計方針に応じて柔軟に採用できる拡張として提供されます。

#### 参照仕様

詳細な技術仕様、検証要件、実装方法については**EIP7951**を参照することが推奨されています。
**EIP7951**はEthereumにおける同じプリコンパイル仕様を定義しているため、Avalancheにおける実装はそれを正確に踏襲するものとなります。

## 互換性

この変更は、新しいプリコンパイルコントラクト（EVMの固定アドレスで動く組み込み処理）を追加するだけで、既存機能は変更しません。

| 観点 | 説明 |
| --- | ---- |
| 未使用アドレスの採用 | 配置先はこれまで使われていないアドレス`0x0000000000000000000000000000000000000100`です。既存コントラクトやプリコンパイルとの衝突を避けます。 |
| 既存仕様の不変更 | 既存のオペコードや合意（consensus）ルールを変更しません。実行規則や状態遷移の互換性は維持されます。 |
| 追加・任意利用（opt-in） | 追加機能であり、コントラクトが明示的に呼び出した場合のみ作用します。既存アプリは影響を受けません。 |

有効化にはC-Chain全体でのネットワークアップグレード（ノードソフトウェア更新の同時適用）が必要です。
一方、Avalanche上のその他のEVM L1やサブネットは、それぞれのクライアントソフトウェアを更新することで、独立してこの拡張を採用できます。
つまり、C-Chainは全体調整が要りますが、各L1/サブネットは自律的に取り込めます。

## セキュリティ

#### 暗号学的セキュリティ

対象の曲線**secp256r1（P-256）**はNIST（米国標準化機関）で標準化され、広く検証されています。
安全性の水準は、EVMの`ECRECOVER`で用いられる**secp256k1**と同程度のものを想定しています。
**ACP204**は**NIST FIPS 186-3**（電子署名標準）に従います。
これにより、署名の正当性判定が標準仕様に沿って一貫して行われます。

#### 実装上のセキュリティ

このプリコンパイルは「**公開鍵で署名を検証する方式**」を採用します。
`ECRECOVER`のように公開鍵（あるいはアドレス）を署名から復元する方式ではなく、入力として与えられた公開鍵と署名の対応を検査する設計です。
P-256の周辺エコシステム（WebAuthnや端末内鍵管理など）と整合しやすい方式です。

また、署名のmalleability（同一メッセージに対して形の異なる署名が成立してしまう可能性）に対する追加チェックは、NIST仕様に合わせてあえて含めていません。
必要に応じて、アプリケーション側やラッパーライブラリで追加の正規化チェックを行う方針が推奨されます。
さらに、入力検証として、曲線上にない点（無効な公開鍵座標）や、範囲外の`r`/`s`が渡された場合は失敗させます。
これにより、不正入力による想定外の挙動を防ぎます。

#### ネットワークセキュリティ

ガスコストは計算量に見合った値が設定されます。
これにより、過度に安い計算で大量の呼び出しを行いリソースを枯渇させるようなDoS（サービス妨害）攻撃のリスクを抑えます。
合意層（consensus）に関しては、一般的なプリコンパイル追加と同様の注意点以外に、特別な新規リスクは想定していません。
ステート遷移ルールを変えないため、合意形成の仕組みに直接の影響はありません。

#### 呼び出しの流れ（イメージ）

```mermaid
sequenceDiagram
    participant Contract as コントラクト
    participant Precompile as プリコンパイル(0x...0100)
    Contract->>Precompile: messageHash, r, s, x, y（合計160B）
    Precompile-->>Contract: 成功=32B(0x...01) / 失敗=データなし
```

## 参考実装

実装は既存の資産とパターンに基づいて進めます。

| 構成要素 | 役割 |
| ------- | --- |
| **EIP7951**のGo-Ethereum実装 | 参照実装として基盤を提供します。P-256検証の仕様とガス見積もりを踏襲します。 |
| Coreth（C-Chain実装）への統合  | AvalancheのC-Chainにおけるプリコンパイル登録と配線（registryへの追加、実行ロジックの接続）を行います。 |
| Go標準暗号ライブラリ | `crypto/ecdsa`および`crypto/elliptic`のP-256実装（FIPS 186-3準拠）を利用し、検証ロジックを組み込みます。 |

実装の進め方は、プリコンパイルの登録と検証ロジックの実装という定番の手順に従います。
以下はあくまで雰囲気を示す擬似コード例です（実際のファイル構成や型名はCoreth/Go-Ethereumの実装に合わせて調整してください）。

```go
// 擬似コード：プリコンパイル登録
var addrP256 = common.HexToAddress("0x0000000000000000000000000000000000000100")

type P256Verify struct{}

func (p *P256Verify) RequiredGas(input []byte) uint64 { 
    return 6900 // EIP-7951ベースの見積り
}

func (p *P256Verify) Run(input []byte) ([]byte, error) {
    // 入力: 160バイト [msgHash(32) | r(32) | s(32) | x(32) | y(32)]
    if len(input) != 160 { return nil, nil /* 失敗=無返却 */ }

    msgHash := input[0:32]
    r := new(big.Int).SetBytes(input[32:64])
    s := new(big.Int).SetBytes(input[64:96])
    x := new(big.Int).SetBytes(input[96:128])
    y := new(big.Int).SetBytes(input[128:160])

    curve := elliptic.P256()
    if !curve.IsOnCurve(x, y) { return nil, nil }

    pub := ecdsa.PublicKey{Curve: curve, X: x, Y: y}
    ok := ecdsa.Verify(&pub, msgHash, r, s)
    if !ok { return nil, nil }

    // 成功時は32バイト(末尾=0x01)を返す
    out := make([]byte, 32)
    out[31] = 0x01
    return out, nil
}

// 起動時にレジストリへ登録
func RegisterPrecompiles(reg map[common.Address]Precompile) {
    reg[addrP256] = &P256Verify{}
}
```

このように、レジストリにアドレスを登録し、**入力検査→曲線上の点か確認→ECDSA検証→成功時32バイト返却／失敗時は無返却**という流れを実装します。
Coreth側では、既存のプリコンパイルと同様に、ハードフォーク（ネットワークアップグレード）で有効化されるブロック以降にこのアドレスを有効化する設定を行います。

## 最後に

今回は「AvalancheのC-ChainにP-256（secp256r1）署名検証のプリコンパイルを追加し、WebAuthnや端末内セキュリティで生成された署名を低ガスでネイティブ検証できる仕組みを提案している**ACP204**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下の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
