Bedrockを理解する:Optimismの配置によるRollupエコシステムの第一歩
原文标题:《Bedrock Explainer》
撰文:Optimism 公式
编译:Frank,Foresight News
Bedrock は OP Stack の歴史上初の正式バージョンの名称であり、Optimism の発展に力を与えるために設計された無料でオープンソースのモジュール式コンポーネントのセットです。
改善の概要
Bedrock はその前身を基に改善され、主に以下を含みます:
- 最適化されたバッチトランザクション圧縮を使用し、Ethereum をデータ可用性層として利用することで、トランザクションコストを削減;
- L1 の再編成をより良く処理することで、L1 トランザクションをロールアップにパッケージ化する際の遅延を短縮;
- コードの再利用を通じてモジュール式証明システムを有効化;
- 設計負債を排除することでノードのパフォーマンスを向上。
より低い手数料
Bedrock はデータコストを最小限に抑えるために最適化されたデータ圧縮戦略を使用しています。現在、この変更の影響をベンチマークテストしていますが、手数料が大幅に削減されると予想しています。
Bedrock はまた、L1 にデータを送信する際の EVM 実行に関連するすべてのガスコストを排除し、以前のバージョンのプロトコルと比較して追加で 10% の手数料を削減します。
より短い入金処理時間
Bedrock はノードソフトウェアに L1 の再編成のサポートを導入し、ユーザーが入金処理を待つ時間を大幅に短縮しました。
このプロトコルの初期バージョンでは、入金処理の確認に最大 10 分かかる可能性がありましたが、Bedrock を使用することで、入金が 3 分以内に確認されると予想しています。
改善されたモジュール式証明
Bedrock は OP Stack から証明システムを抽象化し、ロールアップがロールアップ上での正しい実行を証明するために故障証明または有効性証明(例えば zk-SNARK)を使用できるようにしました。この抽象化により、Cannon を使用してシステム内の故障を証明することも可能になります。
改善されたノードパフォーマンス
以前のバージョンの「各ブロックに1トランザクション」というモデルではなく、単一のロールアップ「ブロック」で複数のトランザクションを実行することで、ノードソフトウェアのパフォーマンスが大幅に向上しました。
これにより、Merkle Trie の更新コストが複数のトランザクションに分散され、現在のトランザクション量では、状態データの増加が年間約 15GB 減少します。
以前のバージョンのプロトコルにおける技術的負債を排除することで、ノードのパフォーマンスもさらに向上しました。これには、L1 のインデックスを作成するために別の「データ転送層」ノードが不要になり、L1 からのトランザクションデータを効率的に照会するためにノードソフトウェアが更新されることが含まれます。
改善された Ethereum の一貫性
Bedrock は最初から Ethereum とできるだけ「一貫性」を持つように設計されており、以前のバージョンのプロトコルにおける Ethereum とのいくつかの偏差が排除されました。これには以下が含まれます:
- 「各ブロックに1トランザクション」のモデル;
- L1 のブロック情報を取得するためのカスタムオペコード;
- JSON-RPC API における L1/L2 手数料フィールドの分離;
- ETH 残高のカスタム ERC20 表現。
Bedrock はまた、EIP-1559、ブロックチェーンの再編成、および L1 に存在する他の Ethereum 機能のサポートを追加しました。
設計原則
Bedrock はモジュール式でアップグレード可能な設計として構築されており、Ethereum の既存コードを再利用し、可能な限り 100% Ethereum 一貫性を達成することを目指しています。
モジュール式
明確に定義されたインターフェースとバージョン管理スキームを使用することで、Bedrock は OP スタック内の異なるコンポーネントを簡単に交換し、新機能を追加できます。
これにより、柔軟なアーキテクチャを活用して Ethereum エコシステムの将来の発展に適応できます。例えば:
- ロールアップノードと実行クライアントの分離;
- モジュール式の障害防止設計。
コード再利用
Bedrock は可能な限り既存の Ethereum アーキテクチャとインフラストラクチャを使用しており、このアプローチはOP Stack が Ethereum メインネットで使用される実戦テスト済みのコードベースからセキュリティとリンディ効果(Lindy effect)の利点を継承できるようにします。
このような例は設計全体に見られます。例えば:
- 最小限の変更を加えた実行クライアント;
- EVM コントラクトではなく、プリコンパイルされたクライアントコード。
Ethereum の一貫性
Bedrock は既存の Ethereum 開発者体験と最大限の互換性を持つことを目指していますが、L1 とロールアップの間の根本的な違いにより、いくつかの例外があります:手数料モデルの違い、より速いブロック生成時間(2 秒対 12 秒)、および L1 入金トランザクションを含む特別なトランザクションタイプ。
これらの例外には以下が含まれます:
- 最小限の変更を加えた Ethereum 実行クライアントの障害証明;
- L2 ネットワーク内のノードとソートエンジンが使用するための Ethereum 実行クライアントのコード再利用。
プロトコル
ロールアップはデータ可用性に基づいて構築され(通常は Ethereum のような L1 ブロックチェーン)、最も一般的な構成では、ロールアッププロトコルは 2 つの主要な情報源から「標準 L2 チェーン」を導出します:
- トランザクションデータはシーケンサー(Sequencer)によって L1 に公開される;
- 入金トランザクションはアカウントとスマートコントラクトによって L1 上のブリッジコントラクトに送信される。
以下はこのプロトコルの基本的な構成要素です:
- L1 上のスマートコントラクトと直接対話することで、入金を「標準 L2 チェーン」に書き込む;
- 出金は「標準 L2 チェーン」に書き込まれ、L1 上のスマートコントラクトおよびアカウントとの対話を暗黙的にトリガーする;
- バッチはロールアップ上のバッチに対応するデータの書き込み;
- ブロック導出は L1 上のデータ読み取りをどのように解釈して「標準 L2 チェーン」を理解するか;
- 証明システムは L1 上に公開された出力ルートの最終性を定義し、それらが実行されることを可能にします(例えば出金の実行)。
入金
入金は L1 上のトランザクションであり、ロールアップに含まれます。定義上、入金は「標準 L2 チェーン」に含まれることが保証されており、これは L2 の検閲または制御を防ぐ手段として機能します。
L1 からの任意のメッセージの伝達
入金トランザクションは入金の一部として行われるロールアップトランザクションです。Bedrock を通じて、入金は完全に汎用的な Ethereum トランザクションであり、Ethereum 上のアカウントまたはスマートコントラクトが「入金」コントラクトを作成できます。
Bedrock は L1 上で利用可能な入金コントラクトを定義しています:これはスマートコントラクトであり、L1 アカウントおよびスマートコントラクトが L2 に書き込むために対話できます。L2 上の入金トランザクションは、この入金コントラクトから発信されたトランザクションから派生し、期待されるパラメータ(例えば from、to、data)を含みます。
詳細については、入金コントラクトプロトコル仕様セクションを参照してください。
L1 で保証された L2 ガスの購入
Bedrock はまた、ガス燃焼メカニズムと入金手数料市場を明確にし、L2 上での入金トランザクションにかかるガスは L1 で購入されたガス燃焼を通じて支払われます。
このガスは具体的に手数料市場で購入され、単一の L1 ブロックに提供されるすべての入金トランザクションのガス総量には厳格な上限があり、このメカニズムは L1 から L2 へのトランザクションを書き込む際に発生する可能性のあるサービス拒否攻撃(DoS)を防ぐために使用されます。この攻撃は、これらのトランザクションが L2 で大量のガスを消費する一方で、L1 では非常に安価であるために発生する可能性があります。
入金トランザクションに提供されるガスは時折「保証されたガス」(Guaranteed Gas)と呼ばれます。Guaranteed Gas の独自性は、L1 でガスを燃焼させることで支払われるため、返金不可であることです。
また、各単位の保証された L2 ガスに必要な燃焼されるべき L1 ガスの総量は、EIP-1559 スタイルの料金メカニズムによって報告された L2 ガス価格に依存します。さらに、ユーザーは計算された料金メカニズムに基づいて消費された L1 ガスの量に応じて動的なガス手当を受け取ります。
詳細な説明については、入金セクションのプロトコル仕様をお読みください。
出金
出金は L2 で開始され、L1 で実行されるトランザクションによって完了するクロスレイヤートランザクションです。注目すべきは、L2 アカウントは出金を使用して L1 コントラクトを呼び出したり、ETH を L2 アカウントから L1 アカウントに移動したりできることです。
出金は L2 で Message Passer 事前デプロイコントラクトを呼び出すことで開始され、このコントラクトはそのストレージにメッセージの重要な属性を記録し、その後 OptimismPortal コントラクトを呼び出して L1 で出金を完了させ、この出金メッセージを証明します。
このように、出金と入金は異なります:出金トランザクションは L1 上のスマートコントラクトを使用して完了する必要があり、ブロックから導出された情報に依存することはありません。
二段階の出金プロセス
出金証明の検証エラーは、過去数年間の多くのクロスチェーンブリッジハッキング事件の根本的な原因です。Bedrock バージョンは、以前のバージョンの出金プロセスに追加のステップを導入し、これらのタイプのエラーに対して追加の防御設計を提供することを目的としています。
二段階の出金プロセスでは、各出金は最終的な退出の 7 日前に出金に対応する Merkle 証明を提出する必要があり、この新しいセキュリティメカニズムは監視ツールに無効な出金証明を探して検出するための 7 日間の時間を提供します。
この期間中に出金証明が無効であることが発見された場合、資金が失われる前にスマートコントラクトをデプロイして修正することができ、クロスチェーンブリッジの妥協リスクが大幅に低減されます。
詳細については、出金プロトコル仕様セクションを参照してください。
バッチトランザクション(Batches)
Bedrock では、L1 と L2 の間のメッセージ伝達のために有線フォーマットを定義しています(つまり、L2 は L1 からブロックを派生させ、L2 はトランザクションを L1 に書き込む)、この有線フォーマットの設計目的は、L1 への書き込みコストとソフトウェアの複雑さを最小限に抑えることです。
最適化されたデータ圧縮
データ圧縮を最適化するために、L2 トランザクションリスト(シーケンサー バッチと呼ばれる)はオブジェクトグループ(チャネルと呼ばれる)に整理され、各チャネルの最大規模は構成可能なパラメータで定義され、最初は 9.5 M に設定されます。これらのチャネルは圧縮機能を使用して圧縮され、L1 に提出されることが期待されています。
バッチの並行提出
L1 に圧縮チャネルデータを提出するシーケンサーからのメッセージを並行化するために、チャネルは「チャネルフレーム」にさらに分解され、これらの「チャネルフレーム」は単一の L1 トランザクションに適合する圧縮チャネルデータブロックです。
「チャネルフレーム」が相互に独立しており、順序が既知であると仮定すると、シーケンサーから L1 に送信される Ethereum トランザクションは並行して送信でき、シーケンサーソフトウェアの複雑さを最小限に抑え、L1 上のすべての利用可能なデータスペースを埋めることができます。
Ethereum ガスの最小化
Bedrock は、L1 システムが「バッチトランザクション」と呼ばれるトランザクションで L1 にチャネルデータを提出する際に使用するすべての実行ガスを削除しました。以前に L1 スマートコントラクトで発生していたすべての検証ロジックはブロック導出ロジックに移動されました。代わりに、「バッチトランザクション」は Ethereum 上の単一の EOA アドレスに送信され、「バッチインボックスアドレス」と呼ばれます。
バッチは依然として有効性チェックを受ける必要があります(つまり、正しくエンコードされている必要があります)、バッチ内の単一のトランザクションも同様です(例えば、署名が有効である必要があります)。無効なバッチと有効なバッチ内の無効な単一トランザクションは、破棄され、システムとは無関係と見なされます。
注意:Ethereum はすぐに EIP-4844 を含む新しいバージョンにアップグレードされ、別のデータ書き込み手数料市場を導入し、Ethereum プロトコルが保存するデータ量の上限を増加させることが期待されており、この変更は L1 にデータを公開する際のコストをさらに削減する見込みです。
詳細な説明については、有線フォーマット仕様をお読みください。
ブロック導出
Bedrock では、このプロトコルの設計は L1 上の入金の時間が「標準 L2 チェーン」のブロック導出に関連していることを保証することを目的としています。これは、シーケンサー、入金、および L1 ブロック属性を通じてデータを L1 に書き込む純粋な関数によって行われます。
これを実現するために、このプロトコルは入金の入金を保証し、L1 と L2 のタイムスタンプを処理し、チャネル内のソートウィンドウを処理して正しい順序を確保するための戦略を定義しています。
入金の保証
ブロック導出プロトコルの目標は次のように定義されています:
各「L2 ブロック間隔」が経過した後、L2 ブロックが存在し、L2 ブロックのタイムスタンプが L1 のタイムスタンプと同期している必要があります(つまり、入金が論理的な時間順序に含まれることを確認します)。
Bedrock では、「シーケンシングエポック」という概念が導入されました:これは、一連の L1 ブロックから導出される L2 ブロックの範囲であり、各エポックは「エポック番号」によって識別され、この「エポック番号」はソートウィンドウ内の最初の L1 ブロックのブロック番号に等しいです。いくつかの制限を受けて、エポックのサイズは異なる場合があります。
バッチ導出チャネルは、「エポック番号」に関連付けられた L1 ブロックのタイムスタンプを、L2 上のトランザクション順序を決定するためのアンカーとして扱います。このプロトコルは、エポックの最初の L2 ブロックが常に一致するエポックの L1 ブロックのタイムスタンプに遅れないことを保証します。エポックの最初のブロックは、入金が処理されることを保証するために L1 上の入金を含む必要があります。
ご注意ください、Bedrock バージョンでは、L2 上のブロック間隔の目標が 2 秒に設定されています。
L1 と L2 のタイムスタンプの処理
Bedrock は、L2 上のタイムスタンプを入金トランザクションに存在する L1 上のタイムスタンプと調整する問題を解決しようとしています。
これは、エポック間の L2 トランザクションに自由にタイムスタンプを適用できるようにするために、非常に短い時間ウィンドウを許可することによって実現されます。
ソートウィンドウ(シーケンシングウィンドウ)は、エポックを導出するための L1 ブロックのシーケンスです。ソートウィンドウ内では、最初の L1 ブロックの番号 N がエポックの「バッチトランザクション」を含みます。
ソートウィンドウにはブロックが含まれ、ソートウィンドウのサイズに依存します:固定のロールアップレベル構成パラメータは少なくとも 2 でなければならず、これを増加させることでシーケンサーは入金に関する L2 トランザクションのソート機会を増やし、減少させることでシーケンサーが「バッチトランザクション」を提出する際により厳しい時間ウィンドウを導入します。これは、MEV 機会を創出することとソフトウェアの複雑さを増加させることとの間のトレードオフです。
「最大シーケンサー漂流」(max sequencer drift)と呼ばれるプロトコル定数は、エポック内のブロックが持つことができる最大タイムスタンプを制御します。この漂流により、シーケンサーは L1 への接続に一時的な問題が発生した場合でもアクティブでいることができます。
ブロック導出パイプライン
「標準 L2 チェーン」は、L2 の創世状態から開始して処理することができ、最初のエポックを設定し、すべてのソートウィンドウを処理して、以下の簡略化された順序に基づいてシーケンサーのバッチと入金の正しい順序パイプラインを決定します:
障害証明
シーケンサーが 1 つまたは複数の L2 ブロックを処理した後、これらのブロックから実行されたトランザクション計算から得られた出力は、L2 から L1 へのメッセージ伝達の信頼性のない実行を実現するために L1 に書き込む必要があります(例えば出金など)。
Bedrock では、出力はツリー構造の形式でハッシュ処理され、出力キャプチャのコストを最小限に抑えます。提案者は定期的に L1 に「標準 L2 チェーン」の Merkle ルートとして出力ルートを提出します。
OP Stack の将来のアップグレードには、出力ルートの正しさを提案者にインセンティブを与えるバインディングを含む障害証明のバリアントの仕様が含まれるべきです。
完全な詳細については、L2 出力ルート提案セクションのプロトコル仕様をお読みください。
実行
Bedrock では、OP Stack は Ethereum の実行層とコンセンサス層の分離をミラーリングし、Ethereum が指定した技術的焦点の分離に大きく依存せざるを得ません。
したがって、Bedrock は同様の方法で実行クライアントとロールアップノードの分離を導入しました。
実行クライアント
実行クライアントは、シーケンサーや他のタイプのノードオペレーターが「標準 L2 チェーン」の状態を決定するために実行するシステムです。また、インバウンドトランザクションの処理やピアツーピア通信、システム状態の処理などの他の機能も実行します。
Bedrock を使用することで、OP Stack は Ethereum 自身の実行クライアント仕様とその多くの実行操作を再利用することを目指しています。このバージョンでは、Bedrock は Ethereum クライアント go-ethereum に対して非常に限られた変更を示しており、その差異は 2000 行未満のコードです。
差異が存在する根本的な理由は 2 つあります:入金トランザクションの処理とトランザクション手数料の徴収です。
入金トランザクションの処理
ロールアップ内で入金されたトランザクションを表現するために、追加のトランザクションタイプが導入されました。実行クライアントは、この新しいトランザクションタイプを EIP-2718 タイプのトランザクション標準に基づいて実装します。
トランザクション手数料の徴収
ロールアップには根本的に 2 つのトランザクション関連の手数料があります:
1 つはシーケンサー手数料です。Ethereum と同じガス表と同じ EIP-1559 アルゴリズムを使用して、オペレーションシーケンサーのコストを計算し、これらの手数料はシーケンサーの操作に使用され、ネットワークの混雑状況に応じて変動します。
もう 1 つはデータ可用性手数料です。データ可用性コストは、バッチ処理トランザクションを L1 に書き込むことに関連し、これらの手数料はシーケンサーが L1 にバッチトランザクションを提出するために支払う必要がある費用を支払うことを目的としています。
Bedrock では、手数料のデータ可用性部分は、GasPriceOracle と呼ばれるロールアップシステムのスマートコントラクト内の情報に基づいて決定され、このスマートコントラクトはブロック導出プロセス中に、各エポックの開始時に挿入された L1 ブロック属性から取得されたガス価格情報に基づいて更新されます。
Bedrock は、JSON-RPC を使用する際にこれら 2 つの手数料を 1 つのフィールドに加算することを指定しています。
ロールアップノード
Ethereum とは異なり、Bedrock には PoS コンセンサスがありません。代わりに、「標準 L2 チェーン」のコンセンサスはブロック導出によって定義されます。OP Stack の実行クライアントは、ロールアップノードと呼ばれるブロック導出を実装する新しいコンポーネントと通信し、このノードは Ethereum と完全に同じエンジン API を使用して実行クライアントと通信します。
ロールアップノードは、L1 上のデータと入金を読み取ることによってシステムの状態を導出する無状態コンポーネントです。Bedrock では、ロールアップノードはユーザーまたは他のロールアップノードからのインバウンドトランザクションをソートするために使用されるか、L1 に依存して L1 に公開された確認済みトランザクションを検証するために使用されます。
ロールアップノードの多様な用途は以下の通りです:
「標準 L2 チェーン」の検証
ロールアップノードを実行する最も単純なモードは、「標準 L2 チェーン」に従うことです。このモードでは、ロールアップノードにはピアノードがなく、L1 からデータを読み取り、ブロック導出プロトコルルールに従ってデータを解釈するためだけに厳密に使用されます。
このノードの目的の 1 つは、プロトコルで定義された他のノードが共有または L1 に公開した出力ルートが正しいかどうかを検証することです。さらに、出力ルートを L1 に提出することを意図している提案者自身も、optimism_outputAtBlock を使用して必要な出力ルートを生成し、L2 出力ルートに対応する 32 バイトのハッシュ値を返すことができます。
そのため、ノードは「確定」(finalized)されたブロックヘッダーに従うだけで済みます。「確定」という用語は Ethereum の PoS コンセンサス(つまり、標準的でほぼ不可逆的なもの)を指し、「確定」された L2 ブロックヘッダーは「確定」された L1 ブロックからのみ導出された「標準 L2 チェーン」のブロックヘッダーです。
L2 ネットワークへの参加
ロールアップノードを使用する最も一般的な方法は、他のロールアップノードのネットワークに参加し、L2 の進行状況と状態を追跡することです。このモードでは、ロールアップノードは L1 から読み取ったデータと入金を同時に読み取り、それをブロックとして解釈し、他のロールアップノードネットワークのユーザーやピアからのインバウンドトランザクションを受け入れます。
ネットワークに参加するノードは、同期している L2 の安全なブロックヘッダーと安全でないブロックヘッダーを使用できます。
- 安全な L2 ブロックヘッダーは、各ブロック(ヘッダーを含む)が完全に参照 L1 チェーンから導出できるロールアップを示し、L1 が「確定」される前(つまり、L1 で再編成が発生する可能性がある);
- 安全でない L2 ブロックヘッダーには、まだ L1 から導出されていない安全でないブロックが含まれます。これらのブロックは、ロールアップノードをシーケンサーとして操作するか、安全でないシーケンサーとの同期から来ます。これも「最新」ブロックヘッダーと呼ばれます。分岐が発生した場合、常に安全な L2 ブロックヘッダーが選択され、安全でない L2 ブロックヘッダーは選択されません。分岐が発生した場合、そのチェーンの安全でない部分は再編成されます;
ほとんどの場合、エンドユーザーアプリケーションにとって、L2 ネットワーク内のロールアップノードは安全でない L2 ブロックヘッダーを参照します。
トランザクションのソート
ロールアップノードを使用する 3 番目の方法は、トランザクションをソートすることです。このモードでは、ロールアップノードは安全でない L2 ブロックヘッダーの上に新しいブロックを作成します。現在、各 OP Stack ネットワークには 1 つのシーケンサーしかありません。
シーケンサーはまた、バッチトランザクションを L1 に公開する責任があり、ネットワーク内の他のノードがそれを同期できるようにします。
バッチャー
シーケンサーの役割はバッチトランザクションを生成することであり、そのためにソートエンジンはロールアップノードを実行し、これらのプロセスはそれらが実行される信頼されたロールアップノードから読み取ることによってバッチ処理を実行します。
これにより、OP Stack の追加コンポーネントであるバッチトランザクション処理プログラムが保証され、ロールアップノードからトランザクションデータを読み取り、L1 に書き込むためのバッチトランザクションとして解釈します。バッチャーコンポーネントは、シーケンサーが実行するロールアップノードの安全でない L2 ブロックヘッダーを読み取り、バッチャートランザクションを作成し、それらを L1 に書き込みます。
標準ブリッジコントラクト
Bedrock には、最も一般的なタイプの入金用のブリッジコントラクトのペアである標準ブリッジコントラクトも含まれています。これらのコントラクトは、入金と出金コントラクトをカプセル化し、ETH および ERC-20 トークンの入金と出金のためのシンプルなインターフェースを提供します。
これらのブリッジコントラクトの設計は、クロスチェーンブリッジの一方にローカルトークンを、もう一方に鋳造と破棄を管理できるカプセル化トークンを含むことを目的としています。ネイティブトークンのブリッジは、ネイティブトークンをコントラクトにロックし、クロスチェーンブリッジの反対側で同量のカプセル化トークンを鋳造することを含みます。
詳細については、標準クロスチェーンブリッジプロトコル仕様セクションを参照してください。
キャノン
Cannon では障害防止構築と検証が実装されていますが、障害証明ゲームの仕様と出力ルートチャレンジャーをロールアップノードに統合することは、後続の仕様マイルストーンの一部です。
延伸読書
プロトコル仕様
プロトコル仕様は OP Stack の技術的詳細を定義しており、プロトコル内部の運用に関する最新の事実の出所です。
Bedrock の違い
Bedrock と以前のバージョンとの違いを詳しく知るには、「Bedrock は何が違うのか」を参照してください。