はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

今回は、Ethereumでブロック提案者が特定のトランザクションを将来のブロックに強制的に含められる仕組み(Inclusion List)を導入し、検閲耐性を高める仕組みを提案しているERC7547についてまとめていきます!

以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。

他にも様々なEIPについてまとめています。

概要

ブロックチェーンの重要な価値の一つに「検閲耐性」があります。 Ethereumにおける「Inclusion List(インクルージョンリスト)」は、この検閲耐性を高めるための仕組みです。 ERC7547では、ブロック提案者(Proposer)が、次に作成されるブロックに必ず含めなければならない特定のトランザクションを指定できます。 これにより、意図的なトランザクション排除を防ぎ、ネットワーク全体の公平性と信頼性を保つことが可能になります。

ERC7547の背景には、Ethereumのコンセンサス層が「The Merge」以降、ブロック提案者とブロック構築者(Builder)を分離する「Proposer-Builder Separation(PBS)」を採用したことがあります。 PBSでは、ほとんどのブロックが専門のBuilderによって構築されますが、その時にBuilderが恣意的にトランザクションを除外する可能性が指摘されています。Inclusion Listは、この課題に対処し、提案者が一定の発言権を持ち続けられるように設計された仕組みです。

動機

The Merge以降、バリデータはほぼ全てのブロック生成を外部のBuilderに委託しています。 2023年10月時点では、約95%のブロックがBuilderによって作成されています。 Builderが生成するブロックは、mev-boostという仕組みを通じて全ての提案者に公平に提供されますが、その反面、どのトランザクションを含めるかの最終判断はBuilderに委ねられます この状況では、提案者は次の2つの選択肢しか持てません。

  1. Builderが作ったブロックをそのまま受け入れ、トランザクション選定への影響力を放棄する。
  2. 自分でブロックを構築し、トランザクションを自由に選べるが、MEV報酬の一部を失う。

Inclusion Listは、このジレンマを解消するために考案されました。 最も単純な案は、スロットNの提案者が、自分のスロットで必ず含めるべきトランザクションを指定するというものです。 しかし、この方法では、Builderが制約を嫌ってブロック構築を拒否する可能性があります。

そこで提案されたのが「Forward Inclusion List(前方インクルージョンリスト)」です。 これは、スロットNの提案者が指定したトランザクションを、次のスロット(N+1)のブロックで必ず含める仕組みです。 ただし、この方式には「無料のデータ可用性(Free Data Availability)」という問題があり、不正にチェーンのサイズを膨らませる恐れがあります。 この問題は、Nonceの再利用や、各スロットに複数のInclusion Listを指定できるようにする工夫で解決可能です。

こうした課題への対策を講じることで、Inclusion Listはインセンティブの不整合やデータ膨張のリスクを回避しつつ、安全に実装できるようになります。

仕組み

定数

ERC7547では、Inclusion Listに関する上限や制約を定義する定数が設定されています。 MAX_TRANSACTIONS_PER_INCLUSION_LIST は1つのInclusion Listに含められるトランザクション数の上限で、最大16件です。 MAX_GAS_PER_INCLUSION_LIST はInclusion List全体で消費できるガス量の上限で、2212^{21}(約200万ガス)に設定されています。 MIN_SLOTS_FOR_INCLUSION_LIST_REQUEST はInclusion Listの要求を出せる最小スロット間隔で、1スロット(約12秒)です。

これらの制限は、リストの肥大化や過剰なガス使用を防ぎ、ネットワーク全体の安定性と効率を維持するために設けられています。

参照オブジェクト

Inclusion Listの構造は複数のデータコンテナで定義されています。 以下はそれぞれの役割です。

InclusionListSummaryEntry

text
class InclusionListSummaryEntry(Container):
    address: ExecutionAddress
    gas_limit: uint64

1件のトランザクションに関する要約情報を格納します。 address はトランザクションの実行先アドレス、gas_limit はそのトランザクションに割り当てられるガス上限を表します。

InclusionListSummary

text
class InclusionListSummary(Container)
    slot: Slot
    proposer_index: ValidatorIndex
    summary: List[InclusionListSummaryEntry, MAX_TRANSACTIONS_PER_INCLUSION_LIST]

あるスロットで提案されたInclusion List全体の要約情報です。 slot はスロット番号、proposer_index は提案者のバリデータインデックスを示します。 summary には最大16件の InclusionListSummaryEntry が含まれます。

SignedInclusionListSummary

text
class SignedInclusionListSummary(Container):
    message: InclusionListSummary
    signature: BLSSignature

InclusionListSummary にBLS署名を付与した構造です。 これにより、提案者が正当にリストを作成したことを暗号的に証明できます。

InclusionList

text
class InclusionList(Container)
    summary: SignedInclusionListSummary
    transactions: List[Transaction, MAX_TRANSACTIONS_PER_INCLUSION_LIST]

署名付きの要約 (summary) と、実際のトランザクション本体を組み合わせた構造です。 これにより、リストの意図と実際の取引内容を紐づけられます。

ExecutionPayload

text
class ExecutionPayload(Container):
    ...
    inclusion_list_summary: List[InclusionListSummaryEntry, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
    inclusion_list_exclusions: List[uint64, MAX_TRANSACTIONS_PER_INCLUSION_LIST]

Ethereumの実行ペイロードにInclusion List関連の情報を追加したものです。 inclusion_list_summary にはリストの要約情報、inclusion_list_exclusions には実際に含められなかったトランザクションのインデックスが記録されます。

ExecutionPayloadHeader

text
class ExecutionPayloadHeader(Container):
    ...
    inclusion_list_summary_root: Root
    inclusion_list_exclusions_root: Root

実行ペイロードのヘッダ部分に、inclusion_list_summary_root(要約情報のMerkle Root)とinclusion_list_exclusions_root(除外リストのMerkle Root)が含まれます。 これにより、ヘッダだけでリストの整合性を検証できます。

BeaconBlockBody

text
class BeaconBlockBody(Container):
    ...
    inclusion_list_summary: SignedInclusionListSummary

ビーコンチェーンのブロック本体に、署名付きInclusion List要約 (SignedInclusionListSummary) が追加されます。 これにより、コンセンサス層でもリストの存在と正当性を確認できます。

コンセンサス層

ERC7547では、Ethereumのコンセンサス層(ビーコンチェーン)と実行層(Execution Layer)が協調して、Inclusion Listを取り扱うための一連の変更が定義されています。 Inclusion Listを導入する目的は、ブロック提案者が一部のトランザクションを将来のブロックに強制的に含められるようにし、検閲耐性を高めることです。

高レベル概要

スロットNでの提案処理

ブロック提案者は、スロットNの時点で署名付きのブロックと、スロットN+1に適用されるInclusion List(要約+トランザクション)をネットワークにブロードキャストします。 Inclusion Listに含まれるトランザクションは、スロットNまたはスロットN+1で実際に含まれる可能性があります。

トランザクションの要約(summary)には、送信元アドレス(originating address)とガス上限が含まれます。 この要約には提案者の署名が付きますが、トランザクション自体には署名は付与されません。

スロットNでの検証処理

バリデータは、スロットNのブロックに対して、少なくとも1つのInclusion Listが見えていなければブロックを検証・選択対象にしません(fork choiceの対象外)。 また、以下の条件が満たされない場合はブロックを無効と判断します。

  • Inclusion Listに含まれるトランザクションがスロットNの時点で実行可能でない場合。
  • トランザクションの maxFeePerGas が現在のスロットのガス価格に対して12.5%以上高くない場合(スロットN+1でも有効であることを保証するため)。
スロットN+1での検証処理

スロットN+1の提案者は、前のスロットNで提出されたInclusion Listの要約に基づき、ブロックを構築します。 このとき、実際の実行ペイロード(ExecutionPayload)には、スロットNで発行されたトランザクションの中で要約に合致するインデックスの一覧を含めます。

このブロックが有効とされるためには、以下の2つの条件が満たされる必要があります。

  • 実行条件 Inclusion List summary の要件を満たし、かつ実行層の観点から実行可能であること
  • コンセンサス条件 前のブロック(スロットN)の署名が含まれており、正しく継続されていること

仕様変更の詳細

ステートトランジション仕様の変更
  • Inclusion Listを扱う新しいデータ構造 inclusion_list を導入します。これにより、提案者はInclusion Listを提出でき、ノードはそれを処理できます。
  • ExecutionPayload と ExecutionPayloadHeader にInclusion Listの情報を保持するためのフィールドが追加されます。
  • BeaconBlockBody に inclusion_list_summary をキャッシュとして保持します。
  • process_execution_payload 関数が拡張され、Inclusion Listの満足性(summaryの条件が満たされているか)を確認します。
フォークチョイス仕様の変更
  • 新たに is_inclusion_list_available チェックを追加し、可視時間内にInclusion Listが存在するかを確認します。
  • 実行層クライアント(EL)への通知メカニズムを実装します。ELがInclusion Listを無効と判断した場合、そのブロックも無効とされます。
P2P仕様の変更
  • GossipネットワークでInclusion Listを取り扱うための新しいバリデーションルールが追加されます。
  • Inclusion Listの送受信用に新しいRPCネットワーク仕様が定義されます。
バリデータ仕様の変更
  • 提案者には、Inclusion Listを作成して署名するという新しい責務が追加されます。
  • BeaconBlockBody作成時の責務にも、Inclusion List summary を含める処理が加わります。

Execution Layer(実行層)

  • get_inclusion_list 関数により、提案者がInclusion Listを取得できるようになります。
  • new_inclusion_list 関数では、ノードがInclusion Listの内容を検証できるようにします。
  • forkchoice_updated 関数が拡張され、ペイロード属性(payload_attribute)にInclusion List summaryを含める仕様になります。
  • new_payload 関数も拡張され、ペイロード内のトランザクションがInclusion List summaryとExclusionsに合致しているかを検証します。
  • 上記の変更に基づく新たなバリデーションルールもExecution-API仕様内で定義されます。

補足

ReducedSummaryとSummaryの選択

元の提案では、データ効率を高めるために「ReducedSummary」と「Rebuilder」を用いる設計が検討されていました。 ReducedSummaryは要約情報を軽量化し、そのままでは完全な情報を持たないため、Rebuilderと呼ばれる仕組みでフルのSummaryを復元する必要があります。

しかしこの方式は、仕様全体を複雑にするというデメリットがあるため、初期バージョンでは通常の「Summary」をそのままブロックに含める簡素な設計が採用されるべきだとされています。

ガス上限の取り扱い

Inclusion Listにガス上限を設定するかどうかは、設計上の重要な選択です。 独立したガス上限をInclusion Listに持たせることで、構造はシンプルになりますが、その反面提案者がInclusion Listのスペースを「売買」できるようになり、不正なサイドペイメントが発生する懸念があります。

逆に、Inclusion Listのトランザクションも通常のブロックガス上限に従わせれば、不正な売買の余地は減りますが、次の提案者がブロックをわざと満杯にしてInclusion Listを無視するような行為が可能になります。 これはガスの無駄遣いというコストを伴いますが、戦略的な行動として現実に起こりうると考えられています。

Inclusion Listの順序と処理タイミング

Inclusion ListはスロットNの「冒頭で」処理されるものとして設計されています。つまり、スロットNのプレステート(事前の状態)に対してInclusion Listの各トランザクションが評価されますが、実際に含める義務があるのはスロットN+1です。これは仕様としての一貫性を保つために必要な処理順序です。

Inclusion Listトランザクションの除外処理

スロットNで提出されたInclusion Listのトランザクションが、同じスロット内で(偶然に)ブロックに含まれる場合もあります。 これは特にmev-boost環境下では避けられない副作用です。 提案者はブロックの中身を事前に完全には把握できないため、トランザクションがすでに満たされることがあるのです。

このため、inclusion_list_exclusion というフィールドが設けられています。 このフィールドには、すでに満たされたトランザクションのインデックスが記録され、ノードはこれをもとにInclusion Listのsummaryから該当トランザクションを除外します。

mev-boostとの互換性

Inclusion Listの導入はmev-boostと直接競合するものではなく、ハードフォーク同様の調整で済みます。 Builderは、Inclusion List summaryに合致しない実行ペイロードを生成した場合、そのブロックが無効と判断されることを理解しておく必要があります。

リレーノード(Relay)は、提案者に署名依頼を送る前にInclusion Listの制約を検証する追加の処理を担う可能性があります。

また、バリデータはブロックヘッダに含まれる inclusion_list_summary_root を自分のローカルな要約と照合し、不一致があればそのブロックを拒否して、自らのローカルブロックを使うという判断も可能です。

同期時の取り扱い(by range / by root)

ノードがチェーンの最新状態に同期する際、そのブロックにInclusion Listが含まれていなければ、そのブロックは無効と見なされて処理されません。 この挙動は、同期ノードがInclusion Listの存在を前提にしているためです。

ただし、全てのブロックにInclusion Listが必要とは限らず、これを制御するパラメータとして MIN_SLOTS_FOR_INCLUSION_LIST_REQUEST が定義されています。 あるブロックのスロット番号とこのパラメータの合計が現在のスロットを下回る場合、そのブロックのInclusion Listチェックはスキップできます。

これはEIP4844における「blob sidecarの保持期間」と同様の考え方で、古いスロットのデータに対しては可用性チェックを省略できるという設計です。

EIP4844については以下の記事を参考にしてください。

互換性

ERC7547は、Ethereumのコンセンサス層におけるブロック検証ルールに対して互換性のない変更を加えるものです。 具体的には、ブロックにInclusion Listの要素(要約やトランザクションの検証など)が含まれていることが、ブロックの有効性を判断する時の新たな条件となるため、旧来の仕様のままでは新しいブロックを正しく検証できません。

そのため、この変更はハードフォーク(強制的なネットワークのアップグレード)を伴う必要があります。 ハードフォークによって全てのノードが新しいルールに一致するよう強制的に更新されることで、ネットワークの整合性が保たれます。

なお、この変更はユーザーの利用体験には直接影響を与えません。 ウォレットの利用や通常のトランザクション送信といった一般的なアクティビティは従来どおり行えるため、ユーザー側での特別な対応は不要です。

セキュリティ

Inclusion Listに関連して最も注意すべき点は、インセンティブ設計の難しさです。 特に、スロットNの提案者がInclusion Listを構築する時、その内容によって次の提案者(スロットN+1)の報酬が減少するようなケースが発生し得ます。

このような状況では、スロットN+1の提案者が、スロットNの提案者に空のInclusion Listを提出するよう金銭的な取引(賄賂)を持ちかける可能性があります。 これはプロトコル自体への直接的な攻撃ではなく、提案者同士の報酬分配に関する非公式な取引(プロフィット・シェア)であり、制度の形骸化を招く恐れがあります。

このような「約束の取り引き(commitment games)」は、Inclusion Listに限らず、他の検閲耐性メカニズムにおいても起こりうる問題です。 したがって、Inclusion Listに固有の欠陥というわけではありませんが、この分野は今も活発に研究が続けられている領域であり、今後の仕様変更が求められます。

引用

mike (@michaelneuder), Vitalik (@vbuterin), Francesco (@fradamt), Terence (@terencechain), potuz (@potuz), Manav (@manav2401), "EIP-7547: Inclusion lists [DRAFT]," Ethereum Improvement Proposals, no. 7547, October 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7547.

最後に

今回は「Ethereumでブロック提案者が特定のトランザクションを将来のブロックに強制的に含められる仕組み(Inclusion List)を導入し、検閲耐性を高める仕組みを提案しているERC7547」についてまとめてきました! いかがだったでしょうか?

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!

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