はじめに

『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個以上のエンコードされたリクエストオブジェクトが含まれます。

javascript
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ハッシュとして計算されます。

python
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などからお気軽に質問してください!

他の媒体でも情報発信しているのでぜひ他も見ていってください!