What might an “enshrined ZK-EVM” look like? 日本語訳
この記事は@VitalikButerinによる「What might an “enshrined ZK-EVM” look like?」を日本語に機械翻訳したものです。
オプティミスティックロールアップやZKロールアップを含むイーサリアム上のレイヤー2 EVMプロトコルは、EVMの証明に依存しています。しかし、これには大規模なコードベースを信頼する必要があり、そのコードベースにバグがあれば、これらのVMはハッキングされるリスクがあります。さらに、L1 EVMと完全互換でありたいZK-EVMでさえ、L1 EVMの変更を自身のEVM実装にコピーするために、何らかのガバナンスが必要であることを意味します。
なぜなら、これらのプロジェクトはイーサリアムのプロトコルにすでに存在する機能を複製しており、イーサリアムのガバナンスがすでにアップグレードやバグの修正に責任を負っているからです!さらに、今後数年間で、ライトクライアントはますます強力になり、L1 EVMの実行を完全に検証するためにZK-SNARKを使用できるようになる日も近いと予想されます。その時点で、イーサリアムネットワークは事実上ZK-EVMを内蔵することになります。そこで、このZK-EVMをロールアップでもネイティブに利用できるようにしたらどうかという疑問が生じます。
この投稿では、実装可能な "enshrined ZK-EVM "のいくつかのバージョンを説明し、トレードオフや設計上の課題、特定の方向に進化しない理由を説明します。プロトコルの機能を実装することの利点と、エコシステムに任せて基本プロトコルをシンプルに保つことの利点を比較検討する必要があります。
ZK-EVMに求められている重要な特性とは?
- 基本機能としてイーサリアムブロックを検証すること。プロトコル機能(今のところ、それがオペコード*1であるか、プリコンパイル*2であるか、あるいは他のメカニズムであるかはオープンなまま)は、入力として(少なくとも)プリステート・ルート、ブロック、ポストステート・ルートを受け入れ、ポストステート・ルートが実際にプリステート・ルートの上でブロックを実行した結果であることを検証する必要があります。
*1オペコード :オペコード(英: opcodeあるいはOpCodeあるいはoperation code) は、操作(operation)に関する命令のコードという意味 引用:Wikipedia
*2プリコンパイル:Web サイト全体をコンパイラに送信するプロセス。結果として得られる Web サイトの出力は、最初の要求でコンパイルする必要なく実行されるため、ソース コードを実行用のサーバーに配置する必要はありません。引用:Weblio国語辞典
- イーサリアムのマルチクライアント哲学との互換性。つまり、単一の証明システムを囲い込むことを避け、代わりに異なるクライアントが異なる証明システムを使用できるようになることが求められます。これにはいくつかのポイントがあります。
- データの可用性要件:ZK-EVMで証明されたEVMの実行に対して、その基礎となるデータが利用可能であることを保証する。
- 証明はEVMとブロック・データ構造の外部に存在すること。ZK-EVM機能は、クライアントによって異なるタイプのSNARKを期待するため、文字通りSNARKをEVM内の入力として受け取ることはありません。トランザクションには証明の必要なステートメント(プレステート、ブロックボディ、ポストステート)が含まれ、オペコードまたはプリコンパイルがこれらのステートメントのコンテンツにアクセスし、クライアントのコンセンサスルールがブロック内で行われる各クレームのデータの可用性と、証明の有無を個別にチェックします。
- 監査可能性。実行が証明された場合、その基礎となるデータが利用可能であることが望ましいです。そうすれば、何か問題が発生したときに、ユーザーや開発者がそれを検査することができます。実際には、データの可用性要件が重要である理由が、さらに1つ追加されることになります。
- アップグレード可能性。特定のZK-EVMスキームにバグが見つかった場合、それを迅速に修正できることが求められます。これは、修正にハードフォークを必要としないことを意味しています。このことは、EVMとブロックデータ構造の外側に存在する証明が重要であるもう一つの理由を追加します。
- EVMの大部分をサポートすること。L2の魅力の一つは、実行レイヤーを革新し、EVMを拡張できることです。あるL2のVMがEVMと少ししか違わない場合、L2がEVMと同じ部分についてはネイティブのプロトコル内ZK-EVMを使用し、異なる部分については独自のコードに頼ることができれば良いです。これは、ZK-EVM機能を設計することで、呼び出し元がビットフィールドまたはオペコードやアドレスのリストを指定し、EVM自体の代わりに外部から供給されるテーブルで処理できるようにすることで実現できます。また、ガスコストを限定的な範囲でカスタマイズできるようにすることもできます。
マルチクライアントシステムにおける
"オープン "VS "クローズド "
"マルチクライアントの哲学 "は、おそらくこのリストの中で最も意見が分かれる要件でしょう。これを放棄して1つのZK-SNARKスキームに集中するという選択肢もあり、これは設計を簡素化しますが、代償としてイーサリアムにとってより大きな「哲学的ピボット」となり(事実上、イーサリアムの長年のマルチクライアント哲学を放棄することになるため)、より大きなリスクを導入してしまいます。長期的な将来、例えば形式的な検証技術がより優れたものになるのであれば、この道を進む方が良いかもしれませんが、現時点ではリスクが大きすぎるように思われます。
もうひとつの選択肢として、プロトコル内で既知の証明システムの固定セットが存在します。それはクローズド・マルチクライアント・システムです。例として、PSE ZK-EVM、Polygon ZK-EVM、Kakarotの3つのZK-EVMを使用することにします。ブロックが有効であるためには、これら3つのうち2つの証明書が必要です。これは単一の証明システムよりは良いですが、ユーザーは存在する証明システムごとに検証機を維持しなければならず、新しい証明システムを組み込むための政治的なガバナンス・プロセスが必然的に発生するなど、システムの適応性が低くなリマス。
このような理由から私は、証明が「ブロックの外」に置かれ、クライアントによって個別に検証される、オープンなマルチクライアント・システムを好んでいます。個々のユーザーは、ブロックを検証するために好きなクライアントを使用し、その証明システムの証明を作成する証明者が少なくとも1人いる限り、それを行うことができます。証明システムは、プロトコル・ガバナンス・プロセスを説得するのではなく、ユーザーを説得して実行させることで影響力を得ることになります。しかし、このアプローチには、後述するように、より複雑なコストがかかることとなります。
ZK-EVMの実装に求められる重要な特性とは?
正しい機能とセキュリティの基本的な保証に加えて、最も重要な特性はスピードです。非同期で、N スロットの遅延の後にのみ各請求に対する回答を返すプロトコル内 ZK-EVM 機能を設計することは可能ですが、数秒以内に証明を生成できることを確実に保証できれば、問題ははるかに簡単になります。
今日、イーサリアムのブロックの証明を生成するには何分も何時間もかかりますが、大規模な並列化を妨げる理論的な理由はないことがわかっています。ブロックの実行のさまざまな部分を個別に証明するために、十分なGPUを常に組み合わせ、再帰的SNARKを使って証明をまとめることができます。さらに、FPGAやASICを使ったハードウェア・アクセラレーションを使えば、証明をさらに最適化できるでしょう。しかし、実際にこのレベルに到達するには、過小評価すべきではない重要なエンジニアリング上の課題があります。
イン・プロトコルZK-EVMの機能は具体的にどのようなものだろうか?
EIP-4844 blob トランザクションと同様に、ZK-EVMクレームを含む新しいトランザクションタイプを導入します:
class ZKEVMClaimTransaction(Container):
pre_state_root: bytes32
post_state_root: bytes32
transaction_and_witness_blob_pointers: List[VersionedHash]
...
EIP-4844のように、mempoolに渡されるオブジェクトは、トランザクションが変更されたバージョンです:
class ZKEvmClaimNetworkTransaction(Container):
pre_state_root: bytes32
post_state_root: bytes32
proof: bytes
transaction_and_witness_blobs: List[Bytes[FIELD_ELEMENTS_PER_BLOB * 31]]
後者は前者に変換できるが、逆はできません。また、ブロックサイドカーオブジェクト(EIP-4844で導入された)を拡張して、 ブロック内で主張されている証明のリストを含むようにしました。
実際には、サイドカーをブロブ用とプルーフ用の2つに分割し、プルーフの種類ごとに別のサブネット(さらにブロブ用の追加のサブネット)を用意するのがよいでしょう。
コンセンサスレイヤーでは、クライアントがブロックの各請求に対して有効な証明を見た場合にのみ、ブロックを受け入れるという検証ルールを追加します。この証明は、transaction_and_witness_blob
の連結が(Block, Witness)
のペアの直列化であるという主張を証明するZK-SNARKでなければならず、Witnessを使用してpre_state_root
の上でブロックを実行すると、(i)有効であり、(ii)正しいpost_state_root
が出力されます。可能性として、クライアントは複数のタイプの証明のM-of-Nを待つことを選択できます。
ここの一つ哲学的な注意点としては、ブロックの実行自体は単にZKEVMClaimTransaction
オブジェクトで提供されるトリプレットと共にチェックされる必要がある(σpre,σpost,Proof)トリプレットの一つとして扱われる可能性があることです。したがって、ユーザーのZK-EVM実装は実行クライアントを置き換えることができます。実行クライアントは、(i)証明者とブロックビルダー、および(ii)ローカルで使用するデータのインデックス付けと保存を重視するノードによって使用されます。
検証と再証明
2つのイーサリアムクライアントがあり、一方がPSE ZK-EVMを使用し、もう一方がPolygon ZK-EVMを使用しているとします。この時点までに、両方の実装が5秒以内にイーサリアムのブロック実行を証明できるところまで進歩しており、それぞれの証明システムに対して、証明を生成するハードウェアを実行する独立したボランティアが十分に多く存在すると仮定します。
残念ながら、個々の証明システムはプロトコル内で固定されていないため、プロトコル内でのインセンティブを設定することはできません。しかし、プルーバー(証明システムの運用者)の運営コストは、研究開発費用に比べて低いと予想されるため、一般的な公共財の資金提供機関を利用してプルーバーを資金援助することが可能です。
誰かがZKEvmClaimNetworkTransaction
を公開したとします。ただし、公開するのはPSE ZK-EVMの証明バージョンだけです。Polygon ZK-EVM のプローバ・ノードがこれを見て、Polygon ZK-EVM 用のプルーフを計算し、オブジェクトを再パブリッシュします。
これにより、最も早くブロックを受理した誠実なノードと、最も遅く同じブロックを受理した誠実なノードとの間の最大待ち時間の合計が δ から 2δ+Tprove (ここでは Tprove<5s)になります.
しかし、この良いニュースは、単一スロットのファイナリティを採用する場合、この余分な遅延を、SSFに固有の複数ラウンドのコンセンサス遅延と一緒に、ほぼ確実に「パイプライン化」できることを意味します。例えば、この4つのサブスロットの提案では、"head vote "ステップでは基本的なブロックの妥当性をチェックするだけで、"freeze and acknowledge "ステップでは証明の存在が必要になるかもしれません。
拡張:"EVMの大部分 "のサポート
ZK-EVM機能の望ましい目標の一つは、「EVMの大部分」をサポートすることです: EVMにはいくつかの追加機能があります。これには、新しいプリコンパイル、新しいオペコード、コントラクトをEVMまたは全く別のVM(例えばArbitrum Stylusのような)のいずれかで記述するオプション、あるいは同期相互通信を行う複数の並列EVMなどが含まれます。
ZKEVMClaimTransaction
が変更されたEVMルールの完全な記述を渡すことができる言語を定義することができます。これは以下のような場合に可能になります:
- カスタムガス料金テーブル(ユーザはガス料金を下げることはできないが、上げることはできる)
- 特定のオペコードを無効にする
- ブロック番号の設定(ハードフォークによって異なるルールを意味する)
- L2用には標準化されているがL1用には標準化されていないEVMの一連の変更、またはその他の単純な変更を有効にするフラグを設定する。
新しいプリコンパイル(またはオペコード)を導入することで、ユーザーがより自由な方法で新機能を追加できるようにするために、ZKEVMClaimNetworkTransaction
のblobの一部として含まれるプリコンパイル入出力トランスクリプトを追加することができます:
class PrecompileInputOutputTranscript(Container):
used_precompile_addresses: List[Address]
inputs_commitments: List[VersionedHash]
outputs: List[Bytes]
Comment
EVMの実行は以下のように変更されます。配列inputs
は空で初期化されます。used_precompile_addresses
のi番目のアドレスが呼び出されたとき、InputsにオブジェクトInputsRecord(calle_address, gas, input_calldata)
を追加し、呼び出しのRETURNDATA
をoutputs[i]
に設定します。最後に、used_precompile_addresses
が全部でlen(outputs)
回呼び出されたことと、inputs_commitments
がinputs
のSSZシリアライゼーションに対するblobコミットメントを生成した結果と一致することをチェックします。inputs_commitments
を公開する目的は、外部のSNARKが入力と出力の関係を簡単に証明できるようにするためです。
ハッシュに格納される入力と、利用可能にしなければならないバイトに格納される出力の非対称性に注目してみてください。これは、入力だけを見てEVMを理解するクライアントが実行できる必要があるためになります。EVMの実行はすでに彼らのために入力を生成しているので、彼らは生成された入力がクレームされた入力と一致することをチェックするだけでよいです。しかし、出力は完全に提供されなければならないので、データ利用可能でなければなりません。
もう1つの有用な機能は、任意の送信者アカウントから呼び出しを行う「特権トランザクション」を許可することです。このようなトランザクションは、他の2つのトランザクションの合間か、プリコンパイルが呼び出されている間の別の(おそらく特権トランザクションでもある)トランザクションの間に実行することができます。これを使用して、EVM以外のメカニズムがEVMにコールバックできるようにすることができます。
この設計は、新規または変更されたプリコンパイルに加えて、新規または変更されたオペコードをサポートするように変更することができます。プリコンパイルだけでも、この設計はかなり強力です。例えば
used_precompile_addresses
に、ステート内のアカウントオブジェクトに何らかのフラグが設定されている通常のアカウントアドレスのリストを含めるように設定し、それが正しく構築されたことを証明するためにSNARKを作成することで、コントラクトがEVMまたはWASM(または別のVM)のいずれかでコードを記述できるArbitrum Stylusスタイルの機能をサポートすることができます。特権トランザクションを使用して、WASMアカウントがEVMにコールバックできるようにすることもできます。- 複数のEVM実行の入出力トランスクリプトと特権トランザクションが正しい方法で一致することを外部でチェックする機能を追加することで、同期チャネルを介して互いに対話する複数のEVMの並列システムを証明できます。
- 4タイプのZK-EVMは、Solidityや他の高級言語をSNARKフレンドリーなVMに直接変換する実装と、それをEVMコードにコンパイルし、祀られたZK-EVMで実行する実装を複数持つことで動作させることができます。2つ目の(必然的に遅くなる)実装は、フォールトプルーバーがバグがあることを主張するトランザクションを送信した場合にのみ実行され、両者が異なる扱いをするトランザクションを提供できれば賞金を受け取ることができます。
- 純粋な非同期VMは、すべての呼び出しをゼロを返すようにし、特権トランザクションへの呼び出しをブロックの最後に追加してマッピングすることで実装できます。
拡張:ステートフル・プローバのサポート
上記の設計の1つの課題は、完全にステートレスであるためデータ効率が悪くなることである。理想的なデータ圧縮を行えば、ERC20の送信はステートレス圧縮のみと比較して、ステートフル圧縮で最大3倍のスペース効率になります。
これに加えて、ステートフルEVMでは、証人のデータを利用可能にする必要はありません。どちらの場合も原理は同じである。EVMの以前の実行で入力された、または生成されたデータであるため、そのデータが利用可能であることがすでに分かっているにも関わらず、利用可能なデータを要求するのは無駄なことになります。
ZK-EVMの機能をステートフルにしたい場合、2つの選択肢があります:
- σpreが、空であるか、あらかじめ宣言されたキーと値のデータ利用可能なリストであること。または、以前の実行のσpost が必要です。
- ブロックによって生成されたレシート R に、blobコミットメントを追加します。これは、(σpre,σpost,Proof) のタプルに含まれます。以前に生成または使用されたblobコミットメント(ブロック、証人、レシート、あるいは通常のEIP-4844 blobトランザクションを表すものを含む)が、時間制限を設けた上で、
ZKEVMClaimTransaction
で参照され、その実行中にアクセスされる可能性があります(例えば、コミットメント i のバイトN...N+k-1をブロック+証人データの位置 j に挿入する一連の命令を通じて)
(1)は基本的に、ステートレスEVM検証を組み込むのではなく、EVMサブチェーンを組み込むということです。(2)は基本的に、以前に使用された、または生成されたブロブを辞書として使用する、最小限の組み込みステートフル圧縮アルゴリズムを作成することです。(2)の場合、(1)の場合よりも時間的な制約がある。
クローズド・マルチプローバとオフチェーン・データに関する議論
閉じた多証明者システムでは、M-of-Nの構造内に固定数の証明システムが存在し、上述の複雑さの多くを避けることができます。特に、閉じた多証明者システムでは、データがオンチェーン上にあることを確認する必要がありません。さらに、閉じた多証明者システムは、ZK-EVMがオフチェーン実行を証明することを可能にし、これによりEVMプラズマソリューションとの互換性が確保されます。
しかし、クローズド・マルチプローバ・システムは、ガバナンスを複雑にし、監査可能性をなくします。
ZK-EVMをプロトコルの機能とする場合、「Layer 2プロジェクト」の継続的な役割は何でしょうか?
現在レイヤ2チームが独自に実装しているEVM検証機能は、プロトコルで処理されることになりますが、レイヤ2プロジェクトは依然として多くの重要な機能を担うことになります:
-
高速な事前確認: Layer 1のスロットが遅くなる可能性がある一方で、Layer 2のプロジェクトは既にユーザーに「事前確認」を提供しています。これは、Layer 2自身のセキュリティによって支えられ、1スロットよりもはるかに低い遅延で提供されます。このサービスは引き続き純粋にレイヤー2の責任で続けられます。
-
MEV緩和戦略: これには暗号化されたメンプール、評判ベースのシーケンサー選択、Layer 1が実装する意志のないその他の機能が含まれる可能性があります。
-
EVMへの拡張: Layer 2プロジェクトは、ユーザーに重要な価値を提供するEVMの大幅な拡張を組み込むことができます。これには「almost-EVM」や、Arbitrum StylusのWASMサポートやSNARKフレンドリーなCairo言語など、根本的に異なるアプローチが含まれます。
-
ユーザーおよび開発者向けの便利さ: レイヤー2チームはユーザーやプロジェクトを自分たちのエコシステムに引き付け、歓迎するために多くの努力をしています。彼らは自分たちのネットワーク内でMEVと混雑料金を取ることで、この努力に対して報酬を受け取っています。この関係は続けられます。
この記事は@VitalikButerinによる「What might an “enshrined ZK-EVM” look like?」を日本語に機械翻訳したものです。
何か修正するべきところや問題があればTwitterにてDMいただければ幸いです。