BOOSTRY Tech Blog

株式会社BOOSTRY の技術ブログです

EIP‑7951: Precompile for secp256r1 Curve Support調査

こんにちは。BOOSTRY エンジニアの大澤です。

今回は、2025年12月にEthereum メインネットでアクティベートされたネットワークアップグレード「Fusaka」(実行レイヤOsaka とコンセンサスレイヤFulu を組み合わせた名称)で導入されたsecp256r1 対応プリコンパイル関数 EIP-7951を解説します。

これまでEthereum L1 上で扱う鍵の管理はUX・セキュリティ・運用負荷の観点でハードルが高いものでした。Fusaka によって追加されたsecp256r1 の高速検証プリコンパイル関数を使えば、WebAuthn やPasskey といった「実社会で広く利用されている認証要素」を直接Ethereum の署名検証に活用できます。その結果、ウォレットのUX 改善やアカウント抽象化を軸にした新しいデバイス認証モデルが現実味を帯びてきました。

この記事では、precompiled contract の内容を改めて整理したうえで、EIP-7951 の仕様、go-ethereum の実装方針、そしてアカウント抽象化との統合例をサンプルとともに紹介します。

※ 本調査はB.O.O.S.T. Lab の活動の一環として実施しました。内容は2025年12月時点の情報に基づいており、リンク先や仕様は将来変更される可能性があります。


1. precompiled contract とは何か

Ethereum 上のスマートコントラクトの処理は、本来EVM バイトコードとしてチェーン上にデプロイされ、opcode を逐次解釈しながら実行されます。しかし、暗号処理のような計算量の大きい処理をEVM 上で純粋に実行すると、ガスコストが現実的ではないという課題があります。

そこでEthereum では、代表的な暗号関数をあらかじめクライアント(go-ethereum など)に「ネイティブ実装」として埋め込み、特定のアドレスに配置する仕組みが採用されています。これが precompiled contract です。

例としてよく知られるものは次の通りです。

アドレス 機能 関連 EIP
0x01 ECRECOVER(ECDSA 署名復元) EIP-196
0x02 SHA-256
0x05–0x08 bn256 曲線演算 EIP-196/197
0x09 BLAKE2b ハッシュ EIP-152

precompile の呼び出しは通常のコントラクト関数である CALL 命令と同じ構文で行われますが、EVM の実行時に「宛先アドレスがprecompile に該当するかどうか」を確認し、ヒットした場合はEVM opcode を経由せず、クライアント内部の高速ネイティブ処理が走ります。

この仕組みはgo-ethereum の vm/contracts.go に実装されており、たとえばアドレス0x01のECRECOVERを呼び出すと、EVMInterpreterの opCallEVM.CallRunPrecompiledContract という経路でネイティブ関数に処理が移ります。

precompile は「コントラクトの皮を被ったネイティブ関数呼び出し」と言えます。

2. secp256r1 が重要視される理由

secp256r1(P-256)は、NIST によって標準化された楕円曲線暗号で、次の場面で広く用いられています。

つまり、現代のエンドユーザーが日常的に利用しているデバイス認証の基盤技術です。

Ethereum では長らくsecp256k1 が唯一の署名アルゴリズムでしたが、これは「エンドユーザーの現実世界の認証体験」とは乖離していました。「Ethereum にログインするためだけの秘密鍵を自分で持つ」というUXが依然として最大の障壁になっていたためです。

コントラクト単体で secp256r1 を実装することもできますが、ガスコストが約300万 gas と高額すぎて実用上の大きな課題でした。 この課題を解消するためにEIP-7951(元はEIP-7212として提案されたもののセキュリティ修正版)が提案されました。

3. EIP-7951:secp256r1 署名検証プリコンパイル

eips.ethereum.org

EIP-7951 では、secp256r1 の署名検証関数を アドレス0x100 に新しい precompile として追加します。

go-ethereum の実装では p256Verify として Osaka Fork に組み込まれており、入力160 バイトを hash / r / s / x / y として扱い、Golang 標準の crypto/elliptic モジュールで検証しています。

func (c *p256Verify) Run(input []byte) ([]byte, error) {
    const p256VerifyInputLength = 160
    if len(input) != p256VerifyInputLength {
        return nil, nil
    }

    // Extract hash, r, s, x, y from the input.
    hash := input[0:32]
    r, s := new(big.Int).SetBytes(input[32:64]), new(big.Int).SetBytes(input[64:96])
    x, y := new(big.Int).SetBytes(input[96:128]), new(big.Int).SetBytes(input[128:160])

    // Verify the signature.
    if secp256r1.Verify(hash, r, s, x, y) {
        return true32Byte, nil
    }
    return nil, nil
}

https://github.com/ethereum/go-ethereum/blob/master/core/vm/contracts.go#L1433

ガスコストは約6,900 gasに収まり、実用十分。従来の「300万gas」と比較すると桁違いに抑えられています。

なお、secp256r1 の署名であってもトランザクション送信のsender recovery は依然secp256k1 前提のため、単体では「EOA をP-256で置き換える」ことはできず、P-256 の署名検証機構をコントラクトコードに含める必要があります。

代表的な利用例として後述するERC-4337(アカウント抽象化)との統合があります。

4. 利用例:ERC-4337 と secp256r1

利用例4

ERC-4337 はアカウント抽象化の規格です。 ユーザー署名を任意形式に拡張できるため、precompile によってsecp256r1 が低コスト化されると、Wallet Contract 内の署名検証ロジックをP-256 ベースに書き換えることが可能になります。

アカウント抽象化の規格や要点については、下記ブログ記事で紹介しています。

tech.boostry.co.jp

ERC-4337 との統合によって、

  1. バイスの生体認証 → WebAuthn 署名生成
  2. Bundler が UserOperation を取りまとめる
  3. Wallet Contract 内で address(0x100) を staticcall して署名を検証
  4. トランザクション実行

というフローが構成できます。

実際に次の構成でサンプルを作成しました。

  • Webフロントエンド:WebAuthn でユーザー登録 & 認証
  • Backend:軽量Bundler API
  • Wallet Contract:P-256 公開鍵登録・署名検証
  • Coin Contract:シンプルな transfer

WebAuthn による署名 → Bundler 経由の実行 → Wallet Contract が0x100 を呼んで検証、という流れで、MetaMask などの秘密鍵を持たずにトランザクション実行が可能であることを確認できています。

また、debug.traceCall を使って内部動作を確認すると、STATICCALL → 0x100 が実行され、署名が正しい場合は 0x1(true) が返却されていることを確認できました。

> debug.traceCall(
  {
    "from":"0x71562b71999873DB5b286dF957af199Ec94617F7",
    "to":"0x9F47649EAc9513B76957946bA9c1E929DDA330cC",
    "data":"XXX"
  }, "latest",
  {"tracer":"callTracer"}
)
// output
{
  calls: [{
      from: "0x9f47649eac9513b76957946ba9c1e929dda330cc",
      gas: "0x2ee9119",
      gasUsed: "0x1af4", // ガスコストは6,900
      input: "XXX",
      output: "0x0000000000000000000000000000000000000000000000000000000000000001",
      to: "0x0000000000000000000000000000000000000100", // static call でaddress 0x100 が呼ばれる
      type: "STATICCALL"
  }],
  from: "0x71562b71999873db5b286df957af199ec94617f7",
  gas: "0x2faf080",
  gasUsed: "0x9312",
  input: "xxx",
  output: "0x0000000000000000000000000000000000000000000000000000000000000001", // 検証の結果、trueが返却される
  to: "0x9f47649eac9513b76957946ba9c1e929dda330cc",
  type: "CALL",
  value: "0x0"
}

5. 利用例:生体認証を使ったマルチシグウォレット

利用例5

EIP-7951 の登場によって、Push 通知 → 端末生体認証 → P-256 署名 → on-chain 検証というシームレスなマルチシグ体験も実現可能になります。

たとえば次のようなモデルです。

  1. signer が Secure Enclave を使って公開鍵を登録
  2. クライアントが「署名依頼 ID」を払い出す
  3. 各 signer の端末へ Push 通知
  4. 生体認証成功時に P-256 署名が生成
  5. Wallet Contract が address(0x100) を叩いて署名を検証
  6. 必要数が揃ったら execute

既存のマルチシグウォレットプロダクトと同様のUX を保ちながら、署名生成を“秘密鍵管理アプリ”から“端末の標準認証システム”へシフトできる点が大きな違いです。

6. まとめ

Fusaka で導入される EIP-7951 は、Ethereum の鍵管理 UX を大きく変える重要なアップグレードです。

  • secp256r1 を高速・低コストでコントラクトロジック内で検証可能
  • WebAuthn/Passkey と自然に統合が可能になり生体認証ベースのウォレットやマルチシグが現実的に
  • 端末やOS が提供する鍵管理(Secure Enclave など)をシームレスに活用可能

これまでEthereum を使うためだけの秘密鍵を保持するというユーザーペインが、現代的な認証基盤と接続する形へ進化しつつあります。

最後に、本記事の内容は社内勉強会資料をもとに再整理したものです。BOOSTRY では毎週、社内で技術勉強会を開催し、ブロックチェーンをはじめとする先端技術の知見をメンバー間で共有しています。この記事を通じて、BOOSTRY の技術への取り組みやブロックチェーン技術の可能性に少しでも興味を持っていただければ幸いです。今後も研究開発およびプロダクト開発を通じて、より効率的で機能性の高い、先進的な金融市場の実現に向けて取り組んでまいります。 引き続き BOOSTRY の活動にご注目ください!

ご興味のある方は、ぜひ採用情報もご覧ください。私たちは、金融×ブロックチェーンという難しくもやりがいのある領域で、新しい市場を共に創る仲間をいつでも歓迎しています。

補足. 参考資料

〒101-0032 東京都千代田区岩本町3丁目9-2 PMO岩本町4F