はじめに
『DApps開発入門』という本や色々記事を書いているかるでねです。
今回は、スマートコントラクトからトリガーされたリクエストを保存し、実行レイヤー(EL)からコンセンサスレイヤー(CL)に共有するための汎用フレームワークを提案しているEIP7685についてまとめていきます!
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。
概要
EIP7685とは、コントラクトからトリガーされたリクエストを保存するための汎用フレームワークを定義した規格のことです。 実行ヘッダーにリクエスト情報を保存するための単一のフィールドを追加します。 リクエストは後でConsensus Layer(コンセンサスレイヤー、CL)に公開され、CLがそれぞれのリクエストを処理します。
主要な特徴
| 特徴 | 説明 |
|---|---|
| 汎用バス | ELからCLへのリクエスト共有のための汎用インターフェース |
| requests_hash | ブロックヘッダーに追加される32バイトのコミットメント値 |
| 拡張性 | 新しいリクエストタイプの追加が容易 |
| 不透明なデータ形式 | 将来的に異なるエンコーディング形式をサポート可能 |
| タイプ別順序付け | リクエストタイプの昇順で整列 |
Ethereumは2つのレイヤーで構成されています。 Execution Layer(EL、実行レイヤー) はトランザクションの実行とスマートコントラクトの処理を担当し、Consensus Layer(CL、コンセンサスレイヤー) はProof of Stakeによるブロックの検証とファイナリティを担当します。
動機
スマートコントラクトで制御されるバリデータの普及により、追加のELトリガー動作への需要が高まっています。 これらのシステムが管理操作を管理用スマートコントラクトに委任できるようにすることで、中間者が介入して特定の操作が確実に行われるようにする必要がなくなります。 これにより、エンドユーザーにとってより安全なシステムが構築されます。
ELトリガー動作の需要
従来、バリデータの引き出しや預け入れなどの操作は、外部のアクターやオラクルに依存する必要がありました。 スマートコントラクトベースのステーキングプールやリキッドステーキングプロトコルが普及するにつれて、これらの操作をコントラクト自体から直接トリガーできることが重要になってきました。
フレームワークの利点
個々のリクエストの詳細をELから抽象化することで、新しいリクエストタイプの追加が簡単になり、実行ブロック構造を更新する必要がありません。
| 利点 | 説明 |
|---|---|
| 中間者不要 | スマートコントラクトが直接管理操作を実行可能 |
| 安全性向上 | 信頼できる第三者への依存を排除 |
| 拡張性 | 新しいリクエストタイプを容易に追加 |
| 構造の安定性 | ブロック構造を変更せずに機能拡張が可能 |
仕様
実行レイヤー
リクエスト構造
requestsオブジェクトは、request_typeバイトと不透明なバイト配列request_dataで構成されます。
request_dataには0個以上のエンコードされたリクエストオブジェクトが含まれます。
requests = request_type ++ request_data各リクエストタイプは独自のrequestsオブジェクトと独自のrequest_data形式を定義します。
| フィールド | 説明 |
|---|---|
request_type |
リクエストの種類を識別する1バイト値 |
request_data |
リクエストの詳細データを含む不透明なバイト配列 |
ブロックヘッダーの拡張
ヘッダーに新しい32バイトのコミットメント値requests_hashを追加します。
ブロックの処理中に、異なるrequest_typeを持つ複数のrequestsオブジェクトがシステムによって生成され、ブロックリクエストリストに蓄積されます。
コミットメントの計算
コミットメントを計算するために、まずブロックリクエストリストの空でないすべてのrequests要素をハッシュ化して中間ハッシュリストを構築します。
空のrequest_dataを持つアイテムは除外されます。
つまり、request_type(1バイト)のみを含み、それ以外に何も含まないrequestsアイテムは中間リストから除外されます。
中間リスト内では、requestsアイテムはrequest_typeの昇順で並べる必要があります。
最終的なコミットメントは、中間要素ハッシュのsha256ハッシュとして計算されます。
def compute_requests_hash(block_requests: Sequence[bytes]):
m = sha256()
for r in block_requests:
if len(r) > 1:
m.update(sha256(r).digest())
return m.digest()
block.header.requests_hash = compute_requests_hash(requests)このコードはrequests_hashを計算する関数です。
block_requestsシーケンス内の各リクエストについて、長さが1より大きい場合(つまり、request_typeだけでなく実際のデータがある場合)、そのsha256ハッシュを累積ハッシュに追加します。
最終的なダイジェストがrequests_hashとなります。
コンセンサスレイヤー
各提案は、新しいELリクエストタイプを含めるためにビーコンチェーンタイプをどのように拡張するかを選択できます。
以下のフロー図は、リクエストがELからCLに伝播される仕組みを示しています。
sequenceDiagram
participant SC as スマートコントラクト
participant EL as 実行レイヤー
participant Block as ブロック
participant CL as コンセンサスレイヤー
SC->>EL: リクエストをトリガー
EL->>Block: requestsオブジェクトを蓄積
Block->>Block: requests_hashを計算
Block->>CL: リクエストを公開
CL->>CL: 各リクエストを処理スマートコントラクトがリクエストをトリガーすると、ELがそれを処理してブロックに蓄積します。
ブロックは全てのリクエストからrequests_hashを計算し、ヘッダーに含めます。
その後、CLがリクエストを受け取り、各リクエストを個別に処理します。
補足
不透明なバイト配列を選択した理由
request_data配列の2バイト目以降を不透明なバイトにすることで(RLPや他のエンコーディングリストではなく)、将来的にSSZ、LEB128、固定幅形式などの異なるエンコーディング形式をリクエストペイロードに対してサポートできます。
| エンコーディング形式 | 説明 |
|---|---|
| RLP | 現在のEthereumで広く使用されている形式 |
| SSZ | Simple Serialize、コンセンサスレイヤーで使用される形式 |
| LEB128 | 可変長整数エンコーディング |
| 固定幅形式 | 固定サイズのデータ形式 |
リクエストのソースと有効性
EIP7685はリクエストがどこから来るか、いつ/どのようにリクエストを検証するかについて厳密な要件を設けていません。 これは将来のプロトコル設計者に最大限の柔軟性を提供するためです。
リクエストのソースに関する推奨事項
リクエストのソースは、トランザクションの実行から来るべきです。 より具体的には、指定されたシステムコントラクトを呼び出してリクエストをアカウントに保存するトランザクションです。 このストレージは、後でコントラクトへのブロック後のシステムコールによって取得されます。
あるいは、システムコールがレート制限に本質的に関与する必要がない場合、ブロック後にシステムによってパースされてリクエストに変換されるイベントを発行することに単に依存することもできます。
有効性検証に関する推奨事項
リクエストの有効性は、多くの場合、実行レイヤーで完全に検証することができません。 これが、それらが単に「リクエスト」と呼ばれる理由です。 リクエストは、一方的にアクションを触媒する権限を単独で持っていません。
システムコントラクトがELで可能な限りの検証を実行し、その後さらなる検証のためにCLに渡すことが期待されます。
順序付けの根拠
タイプ間の順序付けは、タイプの昇順です。
これは、requests_hashにコミットされたすべてのリクエストが一致することを検証するプロセスを簡素化するためです。
| 順序付け方式 | 利点 | 欠点 |
|---|---|---|
| タイプの昇順 | 検証が簡単、整合性を保証 | 生成順序は反映されない |
| 生成順 | 時系列を反映 | ブロック末尾でのシステムコールにより強制が困難 |
代替案として、リクエストがブロック内で生成された順序で並べることも考えられます。 しかし、多くのリクエストがシステムコールを介してブロックの終わりに蓄積されることが予想されるため、これを強制するのは困難です。 したがって、タイプ別の順序付けが整合性を保証する最も簡単な方法です。
タイプ内の順序
同じタイプ内では、順序は定義されていません。 これは、この提案に関する限り、リクエストのデータが不透明だからです。 したがって、各リクエストタイプによって個別に決定されます。
空のリクエストをコミットメントから除外する理由
空のrequests要素をrequests_hashコミットメントから除外することで、ブロックチェーンフォークに依存しない安定した「空」のハッシュ値を得ることができます。
リクエストデータのないブロックの場合、requests_hashは単純にsha256("")となります。
| ケース | requests_hash |
|---|---|
| リクエストなし | sha256("") |
| 空のリクエストのみ | sha256("") |
| 有効なリクエストあり | 中間ハッシュのsha256 |
後方互換性
後方互換性の問題は見つかりませんでした。
EIP7685は新しいフィールドrequests_hashをブロックヘッダーに追加しますが、これはハードフォークを必要とします。
フォーク後、すべてのクライアントは新しいブロック形式を理解する必要があります。
セキュリティ
EIP7685のセキュリティに関しては、まだ議論が必要です。 ただし、以下の点に注意が必要です。
| 考慮事項 | 説明 |
|---|---|
| リクエストの検証 | ELでの部分的な検証とCLでの完全な検証の両方が必要 |
| システムコントラクトのセキュリティ | リクエストをトリガーするシステムコントラクトは慎重に設計する必要がある |
| レート制限 | 悪意あるリクエストの大量発行を防ぐメカニズムが必要になる場合がある |
| ハッシュ衝突 | sha256を使用しているため、衝突耐性は十分 |
引用
最後に
今回は「EIP7685による実行レイヤーからコンセンサスレイヤーへのリクエスト共有フレームワーク」についてまとめてきました! いかがだったでしょうか?
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!
他の媒体でも情報発信しているのでぜひ他も見ていってください!


