はじめに
初めまして。
『DApps開発入門』という本や色々記事を書いているかるでねです。
以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!
今回は、スマートアカウントのアクセスを安全に復旧するための共通インターフェースを提案している「ERC7947」についてまとめていきます。
以下にまとめられているものを解説しながらまとめていきます。
秘密鍵を紛失してもアカウントを復旧できるように、複数のリカバリプロバイダを組み合わせて使える標準的なインターフェースです。
概要
ERC7947は、Account Abstraction Recovery Interface(AARI)と呼ばれるスマートアカウント向けのリカバリインターフェースです。
スマートアカウントが秘密鍵を失った時に、あらかじめ登録しておいたリカバリプロバイダを通じてアクセスを復旧できる仕組みを提供します。
recoverAccess(subject, provider, proof) という関数を中心に、リカバリプロバイダの追加・削除・検証を行う共通インターフェースを定義しています。
どのAccount Abstraction標準(EIP4337やEIP7702等)とも組み合わせられる設計になっており、スマートアカウントの種類を問わず利用できます。
EIP4337については以下の記事を参考にしてください。
EIP7702については以下の記事を参考にしてください。
動機
Account Abstraction(アカウント抽象化)によりスマートアカウントが普及すると、ユーザーは秘密鍵を直接管理しなくてもよい体験が実現します。
しかし、秘密鍵を紛失した場合のアクセス復旧方法が標準化されていないという課題がありました。
秘密鍵紛失の課題
EOA(Externally Owned Account)では秘密鍵を失うとアカウントのすべてにアクセスできなくなります。
スマートアカウントでも同様のリスクがあり、何らかのリカバリ手段が必要です。
しかし、現在のスマートアカウントは各プロジェクトが独自のリカバリ方法を実装しており、互換性がありません。
ZKAIとZK2FAの可能性
Zero-Knowledge Artificial Intelligence(ZKAI)やZero-Knowledge Two Factor Authentication(ZK2FA)といった技術が登場しています。
これらの技術を活用すれば、秘密鍵以外の方法で本人であることを証明し、アカウントへのアクセスを復旧できます。
ZKAIとZK2FA
ZKAIはゼロ知識証明とAIを組み合わせた技術で、例えば生体認証データをプライバシーを保護したまま検証できます。
ZK2FAはゼロ知識証明による二要素認証で、秘密の情報(パスワードやワンタイムコード等)を直接公開せずにその知識を証明できます。
これらはリカバリプロバイダとして実装でき、秘密鍵に代わる復旧手段を提供します。
リカバリプロバイダマーケットプレイス
ERC7947では、スマートアカウントが複数のリカバリプロバイダを登録できる「リカバリプロバイダアグリゲータ」として機能します。
ユーザーは複数のリカバリ手段を組み合わせられるため、中央集権的なサービスやプロジェクトに依存する必要がなくなります。
共通インターフェースが標準化されることで、リカバリプロバイダのマーケットプレイスが生まれる可能性もあります。
仕様
IAccountRecoveryインターフェース
スマートアカウントが実装するインターフェースです。
リカバリプロバイダの管理とアクセス復旧の機能を提供します。
interface IAccountRecovery {
event AccessRecovered(bytes subject);
event RecoveryProviderAdded(address indexed provider);
event RecoveryProviderRemoved(address indexed provider);
function addRecoveryProvider(address provider, bytes memory recoveryData) external payable;
function removeRecoveryProvider(address provider) external payable;
function recoveryProviderAdded(address provider) external view returns (bool);
function recoverAccess(
bytes memory subject,
address provider,
bytes memory proof
) external returns (bool);
}
addRecoveryProvider
リカバリプロバイダを追加する関数です。
-
引数
-
provider
追加するリカバリプロバイダのアドレス。 -
recoveryData
リカバリプロバイダに渡すカスタムデータ(コミットメント)。
-
- アクセス制御されるべきです。
-
providerがaddress(0)でないことを確認しなければなりません。 -
providerのsubscribe関数を呼び出し、recoveryDataを渡さなければなりません。
removeRecoveryProvider
登録済みのリカバリプロバイダを削除する関数です。
-
引数
-
provider
削除するリカバリプロバイダのアドレス。
-
- アクセス制御されるべきです。
-
providerのunsubscribe関数を呼び出さなければなりません。
recoveryProviderAdded
リカバリプロバイダが登録済みかどうかを確認するview関数です。
-
引数
-
provider
確認するプロバイダのアドレス。
-
-
戻り値
- 登録済みなら
true、未登録ならfalse。
- 登録済みなら
recoverAccess
アカウントのアクセスを復旧する関数です。
-
引数
-
subject
復旧対象(エンコードされたオーナーアドレス、アクセス制御ロール等)。 -
provider
使用するリカバリプロバイダのアドレス。 -
proof
リカバリの証明(ZKP/ZKAI、署名等)。
-
-
戻り値
- 復旧成功なら
true、失敗ならfalseまたはリバート。
- 復旧成功なら
-
providerがアカウントに登録されていることを確認しなければなりません。 -
providerのrecover関数を呼び出さなければなりません。 - 証明の検証に成功した場合、
subjectに従ってアカウントのアクセスを更新しなければなりません。
リカバリフロー
アカウント復旧は以下の流れで行われます。
- ユーザーは事前に
addRecoveryProviderでリカバリプロバイダを登録しておきます。この時、リカバリプロバイダに「コミットメント」(秘密のハッシュ値等)を渡します。 - 秘密鍵を紛失した場合、ユーザーは
recoverAccessを呼び出します。 -
recoverAccessはリカバリプロバイダのrecover関数を呼び出し、ユーザーが提出した証明(proof)を検証・実行します(nonceを更新して再利用を防止します)。 - 証明が正しければ、スマートアカウントのアクセス権が
subjectに基づいて更新されます。
IRecoveryProviderインターフェース
リカバリプロバイダが実装するインターフェースです。
スマートアカウントからのサブスクリプション管理とリカバリ証明の検証を行います。
interface IRecoveryProvider {
event AccountSubscribed(address indexed account);
event AccountUnsubscribed(address indexed account);
function subscribe(bytes memory recoveryData) external payable;
function unsubscribe() external payable;
function getRecoveryData(address account) external view returns (bytes memory);
function recover(bytes memory object, bytes memory proof) external;
}
subscribe
スマートアカウント(msg.sender)をリカバリプロバイダに登録する関数です。
recoveryDataをmsg.senderに紐づけて保存し、後のrecover関数での証明検証に使われるコミットメントとして管理します。
-
引数
-
recoveryData
リカバリのコミットメント(ハッシュ値やZKP公開出力等)。
-
unsubscribe
スマートアカウントのサブスクリプションを取り消す関数です。
-
msg.senderに関連するすべてのリカバリデータを削除しなければなりません。
getRecoveryData
アカウントのリカバリデータ(コミットメント)を取得するview関数です。
-
引数
-
account
リカバリデータを取得するアカウントのアドレス。
-
-
戻り値
- 関連するリカバリデータ。
recover
msg.sender(スマートアカウント)のリカバリを実行する関数です。
msg.senderのrecoveryDataを使ってproofの妥当性を確認し、証明の再利用を防ぐためにnonceなどを更新しなければなりません。
証明が無効な場合はリバートします。
-
引数
-
object
新しいオブジェクト(subjectとは異なる場合がある)。 -
proof
リカバリの証明。
-
subscribe/recoverの流れ
リカバリプロバイダとスマートアカウントの関係は「サブスクリプションモデル」になっています。
subscribeでは、スマートアカウントがリカバリプロバイダに「コミットメント」を渡して登録します。
このコミットメントは、秘密の情報のハッシュ値やZKPの公開出力のようなもので、秘密そのものは渡しません。
recoverでは、ユーザーが提出したproofがコミットメントと整合するかを検証します。
例えばZKP(ゼロ知識証明)を使えば、秘密の情報を明かさずに「自分がその秘密を知っている」ことを証明できます。
証明の再利用を防ぐためにnonceの更新が求められており、リプレイ攻撃(同じ証明を使い回す攻撃)が防止されます。
補足
設計の背景
ERC7947はいくつかの設計判断に基づいています。
任意のAA標準との互換性
この提案は特定のAccount Abstraction標準に依存しません。
EIP4337でもEIP7702でも、スマートアカウントがIAccountRecoveryインターフェースを実装するだけでリカバリ機能を利用できます。
これにより、アカウントリカバリの市場が特定のAA標準に縛られずに成長できます。
subjectとobjectがbytesである理由
recoverAccessのsubjectパラメータとrecoverのobjectパラメータは、アドレスではなくbytes型です。
スマートアカウントの中にはオーナーアドレスを持たないものもあり、ロールベースのアクセス制御を採用しているケースもあります。
bytes型にすることで、エンコードされたオーナーアドレス、アクセス制御ロール、その他のカスタムデータなど、柔軟な復旧対象を指定できます。
再コミットの方法
セキュリティ上の理由でコミットメントを更新したい場合は、unsubscribeとsubscribeをマルチコールで連続実行します。
これにより、古いコミットメントを削除してから新しいコミットメントを登録できます。
後方互換性
ERC7947は既存のスマートアカウントの仕様に影響を与えません。
IAccountRecoveryインターフェースを実装しない既存のコントラクトはそのまま動作し続けます。
セキュリティ
アカウントリカバリには重要なセキュリティ上の考慮事項があります。
アクセス制御の重要性
addRecoveryProviderとremoveRecoveryProvider関数は適切にアクセス制御されなければなりません。
これらの関数が誰でも呼び出せる状態だと、攻撃者が悪意のあるリカバリプロバイダを追加してアカウントを乗っ取る可能性があります。
フィッシング攻撃のリスク
ユーザーが騙されて悪意のあるリカバリプロバイダを追加してしまうリスクがあります。
悪意のあるリカバリプロバイダは偽のリカバリ証明を受け入れることで、アカウントの完全な制御権を得る可能性があります。
リカバリプロバイダの追加時にはプロバイダの信頼性を十分に確認することが重要です。
引用
最後に
今回は「ERC7947(Account Abstraction Recovery Interface)」についてまとめてきました。
スマートアカウントの秘密鍵を紛失した時に、あらかじめ登録しておいたリカバリプロバイダを通じてアクセスを復旧できる共通インターフェースを定義した提案です。
ZKPやZKAIを活用したリカバリプロバイダのマーケットプレイスが生まれる可能性もあり、Account Abstractionのユーザー体験をさらに向上させる重要な仕組みです。
他でも色々記事を書いているのでぜひよろしければ読んでいってください!

