---
title: "アカウント抽象化 パート4: 集約署名"
description: "ERC-4337における集約署名の仕組みを解説。単一の暗号署名で複数のUser Opの検証をまとめ、トランザクション処理の効率を高める。"
---

## Aggregate signatures

現在の実装では、バンドル内の各ユーザーオペレーションを個別に検証しています。これは検証を考える上で非常に素直な方法ですが、無駄が生じる可能性があります。署名の検証には暗号学的な演算がかなり必要になるため、ガス代の面でコストが高くなりがちです。

**多数の署名の代わりに1つの署名だけで、多くのオペレーションを同時に検証できたら良いと思いませんか?**

これを実現するには、暗号学のある概念、**集約署名（aggregate signatures）** が鍵になります。

集約に対応した署名方式では、異なる鍵で署名された複数のメッセージが与えられたとき、1つの結合署名を生成する方法が提供されます。この結合署名を検証することは、構成要素であるすべての署名が有効であることを意味します。

集約に対応する署名方式の代表例が[BLS](https://en.wikipedia.org/wiki/BLS_digital_signature)です。

この最適化はRollupsの実装において特に有用です。Rollupsの主な目的はデータ圧縮であり、署名の集約によって署名部分を圧縮できるためです。

署名集約によるスペース削減については、[Vitalikのこの件に関するツイート](https://twitter.com/VitalikButerin/status/1554983955182809088)を参照してください。

### アグリゲーターの導入

まず気づくのは、バンドル内のすべてのユーザーオペレーションの署名を一緒に集約できるわけではないということです。ウォレットは、与えられた署名を検証するために任意のロジックを使用することが許されているため、同じバンドル内にさまざまな署名方式が存在する可能性があることを思い出してください。

異なる方式間の署名は基本的に集約できないため、バンドルは最終的に複数のグループに分かれることになります。各グループは、特定の集約方式を使うか、あるいはまったく集約を行わないかのいずれかになります。

オンチェーンでさまざまな集約方式をそれぞれ独自のロジックとともに表現する必要があるため、各集約方式を**アグリゲーター**と呼ぶコントラクトで表現することにします。

集約方式は、複数の署名を1つに結合する方法と、その結合署名を検証する方法によって定義されます。したがって、アグリゲーターはこの2つの機能をメソッドとして公開します。

<ImageBlock
  src="https://media.alchemy.com/1704793497-aggregator-contract-combining-user-ops-to-single-signature.jpeg"
  alt="アグリゲーターコントラクトが複数ユーザーのオペレーションを1つの署名を持つグループにまとめる様子"
  width={960}
  height={540}
  caption="アグリゲーターコントラクトが複数ユーザーのオペレーションを1つの署名を持つグループにまとめる様子"
/>

各ウォレットが独自の署名方式を定義しているため、どのアグリゲーターと互換性があるか（あるとすれば）を決めるのは各ウォレット次第です。

**ウォレットが集約に参加したい場合、自身のアグリゲーターを選択するメソッドを公開します：**

この新しい`getAggregator`メソッドを使うことで、バンドラーは同じアグリゲーターを持つオペレーションをグループ化し、そのアグリゲーターの`aggregateSignatures`メソッドを使って結合署名を計算できます。

**グループは次のようになります：**

<CalloutBlock>

💡 バンドラーが特定のアグリゲーターについてオフチェーンの知識を持っている場合、`aggregateSignatures`をEVMコードとして実行する代わりに、署名集約アルゴリズムのネイティブ版をハードコードすることで最適化できます。

</CalloutBlock>

次に、新しいアグリゲーターを利用できるように、エントリーポイントコントラクトを更新する必要があります。

エントリーポイントには、オペレーションのリストを受け取る`handleOps`メソッドがあったことを思い出してください。

**ここに新しいメソッド`handleAggregatedOps`を追加します。これは同じことを行いますが、アグリゲーターごとにグループ化されたオペレーションを受け取ります：**

新しいメソッド`handleAggregatedOps`は、`handleOps`とほぼ同じように動作します。唯一の違いは検証ステップにあります。

`handleOps`が各ウォレットの`validateOp`メソッドを呼び出すことで検証を行うのに対し、`handleAggregatedOps`は代わりに、各グループのアグリゲーターを使って、そのグループの結合署名に対しアグリゲーターの`validateSignatures`メソッドを呼び出します。

<ImageBlock
  src="https://media.alchemy.com/1703863779-account-abstraction-key-concepts.jpeg"
  alt="図：エグゼキューターがアグリゲーターを使ってユーザーオペレーションをグループ化し、一括検証のためにエントリーポイントへ送る様子"
  width={960}
  height={540}
  caption="エグゼキューターはアグリゲーターを使ってオペレーションをグループ化してからエントリーポイントに送るため、それらをすべて同時に検証できます。"
/>

もうすぐ完成です！

しかし、ここでもう1つ、すでにおなじみの問題があります。

バンドラーは、あるオペレーションのグループをバンドルに含める前に、アグリゲーターがそのグループを検証することをシミュレーションで確認したいと考えています。なぜなら、検証が失敗するとバンドラーがガス代を負担することになるからです。しかし、任意のロジックを持つアグリゲーターは、シミュレーション時には簡単に成功しても、実行時には失敗する可能性があります。

これは、ペイマスターやファクトリーで行ったのとまったく同じ方法で解決します。つまり、アグリゲーターがアクセスできる[ストレージ](https://www.alchemy.com/docs/smart-contract-storage-layout)とオペコードを制限し、ストレージにアクセスしない場合を除き、エントリーポイントにETHをステークすることを要求します。

これで集約署名については以上です！

### まとめ

ここまでで作り上げたものは、ほぼ[ERC-4337の全体アーキテクチャ](https://eips.ethereum.org/EIPS/eip-4337)そのものです！一部のメソッドの名前や引数など、細部にはいくつかの違いがありますが、アーキテクチャ上の違いと呼べるものはもう残っていないと思います。私がうまく説明できていれば、あなたは今、実際のERC-4337を読んで、何が起きているのか理解できるはずです。

ここまで読んでくださった方、私の説明を読んでいただき本当にありがとうございました！この文章を書くことが私にとって役立ったのと同じくらい、皆さんの役にも立てていれば嬉しいです。

## 補遺：ERC-4337との違い

ここまででアカウントアブストラクションの全体的なアーキテクチャを見てきましたが、ERC-4337を考えた優秀な人たちは、上記で説明した内容とはやや異なる点をいくつか考案しています。

そのいくつかを見ていきましょう！

### 1. 検証の有効時間範囲

上では、ウォレットの`validateOp`とペイマスターの`validatePaymasterOp`の戻り値の型について、かなり曖昧に説明していました。ERC-4337はこれをうまく活用する方法を見つけています。

ウォレットがぜひ行いたいことの1つが、あるユーザーオペレーションを一定期間だけ有効にすることです。そうしないと、悪意のあるバンドラーがそのオペレーションを長期間保持し、後になってバンドラーにとって有利なタイミングでバンドルに含めることができてしまいます。

ウォレットは、検証時に`TIMESTAMP`をチェックして未来すぎないことを確認することでこれを防ぎたいと考えるかもしれませんが、それはできません。なぜなら、シミュレーションの精度が損なわれないよう、検証時の`TIMESTAMP`の使用を禁止したからです。つまり、ウォレットはオペレーションがどの時間範囲で有効かを示す別の方法が必要になります。

**そこで、ERC-4337は`validateOp`にウォレットが時間範囲を選択できる戻り値を持たせています：**

この戻り値は、オペレーションが有効な時間範囲を、8バイト整数2つを連続させたものとして表します。

ERC-4337からもう1つ補足すると、検証失敗の場合、ウォレットはrevertするのではなくセンチネル値を返すべきとされています。これはガス見積もりに役立ちます。[eth_estimateGas](https://www.alchemy.com/docs/chains/ethereum/ethereum-api-endpoints/eth-estimate-gas)は、revertするトランザクションでどれだけガスが使われたかを教えてくれないためです。

### 2. ウォレットとファクトリー向けの任意のコールデータ

私たちのウォレットのインターフェースは次のようなものだと説明しました：

ERC-4337では、実はウォレットは`executeOp`という名前のメソッドを持ちません。

**代わりに、ユーザーオペレーションには`callData`フィールドがあります：**

これがコールデータとしてウォレットに渡されます。

一般的なスマートコントラクトでは、このデータの最初の4バイトが関数セレクタとして解釈され、残りが関数の引数として解釈されます。

つまり、必須の`validateOp`メソッド以外については、ウォレットは独自のインターフェースを定義でき、ユーザーオペレーションを使ってウォレット上の任意のメソッドを呼び出すことができます。

同様に、ERC-4337ではファクトリーコントラクトも実際には`deployContract`メソッドを持ちません。ファクトリーもまた、オペレーションの`initCode`フィールドから任意のコールデータを受け取ります。

### 3. ペイマスターとファクトリー向けのコンパクトなデータ

上では、ユーザーオペレーションにはペイマスターを指定するフィールドと、そのペイマスターに渡すデータを指定するフィールドが含まれていると説明しました：

**ERC-4337では、最適化として、これらが1つのフィールドに統合されています。そのフィールドの最初の20バイトがペイマスターのアドレスで、残りがデータです：**

ファクトリーとそれに送られるデータについても同様です。私たちは`factory`と`factoryData`という2つのフィールドを使っていましたが、ERC-4337ではこれらを`initCode`という単一のフィールドに統合しています。

さて、これで完了です！

アカウントアブストラクションについて多くのことを学んでいただけたなら幸いです。

### アカウントアブストラクションはあなたにも発明できた

この4部構成シリーズの最初を見逃しましたか？最初から読み直してみてください！

1. [Account Abstraction Part 1: Protect Our Assets](https://www.alchemy.com/overviews/what-is-account-abstraction)
1. [Account Abstraction Part 2: Sponsoring Transactions with Paymasters](https://www.alchemy.com/overviews/what-is-account-abstraction-paymasters)
1. [Account Abstraction Part 3: Wallet Creation](https://www.alchemy.com/overviews/what-is-account-abstraction-wallet-creation)
