zkEVMに関するあれこれ
ここでEIP化に向けた議論が始まった。しかし、まだまとまりがない。
そもそも、zkEVMはzk-Rollupを最適化させるために生み出された機構であり、各チームが採用しているzkスキームなどに依存して開発されている。共通するのはzk-SNARK(STARK)を使ってトランザクションの実行を暗号的に証明することで、Ethereumチェーン自体の検証をより簡単にするということ。
zk-Rollupに絶対必要ってわけではない。開発難易度も高いと言われている。
zk-Rollupの最適化
zk-Rollupでは実行結果をバッチしてLayer1に投下するわけだが、Ethereumは元々zk-Rollupを前提とした設計ではないので、その証明-検証プロセスはEVMに搭載されていない。
また、現状ではゼロ知識証明を作るプロセスは証明者(zk-Rollupでいうところのブロックを作る人)に多大な計算量を強いる。
そこで、zkフレンドリーなハッシュ関数やハードウェアなどを用いて計算量の削減に取り組んでいる。
このように、ナチュラルなEVMと比べてzk-Rollupは独自の最適化のためにやることが多く、EVMのエコシステムをそのまま引き継ぐことは難しい。
ビタリクによる分類
zkEVMと言われている概念は明確に定義されていないが、ビタリクが幾つかに分類してくれた。
https://scrapbox.io/files/63ac5fd3c6e0ac001ebe7a5d.png
https://vitalik.ca/general/2022/08/04/zkevm.html
横軸:zkEVMとしてのパフォーマンス、縦軸:EVMとの互換性としたときに五つに分類されている。
前述の通り、パフォーマンスも互換性も満たすzkEVMが理想と言える。
Type 1 (fully Ethereum-equivalent)
理想は、現在のEthereumブロックをそのまま検証できること、少なくともexcution Layerを検証できること
つまり、すべてのTx、スマートコントラクト、アカウントロジックのexcutionを検証できること
タイプ1のzkEVMは、最終的にEthereumのレイヤー1自体をよりスケーラブルにするために必要で、長期的には、タイプ2またはタイプ3のZK-EVMでテストされたEthereumの修正がEthereum本体に導入されるかもしれないが、そのような再設計には複雑さが伴う。
理想的なタイプ1のZK-EVMは、多くのインフラを再利用できるため、ロールアップに最適と言える。
例えば、Ethereumの実行クライアントは、ロールアップブロックの生成と処理にそのまま使用することができるので、ブロック探索者やブロック生成などのツールは非常に簡単に再利用可能になる。
なぜ
Type 1はEthereumの完全な複製を目指しているため、証明生成に生じる非効率性を軽減する手段がない。
現在、イーサリアムのブロックの証明には何時間もかかっている。これは、証明の並列化(再帰証明)や長期的にはZK-ASICによって軽減される。
Type 2 (fully EVM-equivalent)
タイプ2のZK-EVMは、タイプ1に比べてEthereumと完全に同等であるわけではない。 目標は、既存のアプリケーションと完全な互換性を持ちつつ、開発を容易にし、証明生成を高速化するために、Ethereumに若干の修正を加えること。
「内部からは」Ethereumと全く同じに見えるが、外部、特にブロック構造やステートツリーのようなデータ構造ではいくつかの違いがある
タイプ2のZK-EVMは、Ethereumのstateなどを保持するデータ構造に変更を加える。これらの構造はEVM自体が直接アクセスすることができないため、Ethereum上で動作するアプリケーションは、ほとんどの場合、タイプ2のzkEVM上でも動作する。
多少の修正を加えればEthereumの実行クライアントをそのまま使用することは可能であり、EVMのデバッグツールやその他のほとんどの開発者用インフラも同様。
ブリッジのように過去のTx、receipt、stateに関する主張を検証するために過去のEthereumブロックのMerkle証明を検証するアプリケーション、将来のEthereumの変更(例えばVerkle tree)に目を向けると、Keccakを別のハッシュ関数に置き換えたZK-EVMはこれらの仕組みを壊してしまう可能性がある。
より良い代替案は、Ethereum 自身が将来を保証する履歴アクセスのプリコンパイルを追加すること。
タイプ2は、不必要に複雑でZKに不親切な暗号に依存しているEthereumスタックの部分を取り除くことで、タイプ1よりも証明時間を短縮できる。特に、EthereumのKeccakとRLPベースのMerkle Patricia木、そしてブロックとレシート構造を変更する可能性がある。
例えば代わりに別のハッシュ関数Poseidonを使用するかもしれないし、コードハッシュとKeccakを格納するためにステートツリーを変更し、EXTCODEHASHおよびEXTCODECOPYオペコードを処理するためにハッシュを検証する必要性をなくすことも考えられる。
とはいえ、EVMに固有の非効率性やZKに不親切な点があるため、EVMをそのまま証明しなければならないことによる遅さは依然として残っている。
オペコードMLOADは、「アラインされていない」チャンク(開始と終了が32の倍数でない)を含む任意の32バイトを読むことができるので、MLOADは単に1つのチャンクを読むと解釈することはできない。
Type 2.5 (EVM-equivalent, except for gas costs)
最悪ケースでの検証時間を大幅に改善する方法の1つは、ZK-proveが非常に困難なEVM内の特定の操作のガスコストを大幅に増加させることです。これには、プリコンパイル、KECCAKオペコード、およびコントラクトの呼び出し、メモリやストレージへのアクセス、復帰の特定のパターンが含まれる場合があります。
ガスコストの変更は、開発者のツールの互換性を低下させ、いくつかのアプリケーションを破壊するかもしれませんが、一般的に「深い」EVMの変更よりリスクが低いと考えられています。開発者は、ブロックに収まる以上のガスをトランザクションで必要としないように、また、ハードコードされたガス量で呼び出しを行わないように注意する必要があります(これはすでに長い間、開発者のための標準的なアドバイスでした)。
リソース制約を管理する別の方法として、各操作が呼び出される回数にハードリミットを設定する方法があります。これは回路に実装するのは簡単ですが、EVMのセキュリティの仮定とあまりうまくかみ合いません。私はこの方法をタイプ2.5ではなく、タイプ3と呼びます。
ガスコストを上げることがなぜ検証時間に関係あるのかわからない
Type 3 (almost EVM-equivalent)
タイプ3のZK-EVMはプリコンパイルが特徴。さらに、タイプ 3は、コントラクトコード、メモリ、スタックの扱いに若干の違いがある。
タイプ 3 の 目標は、ほとんどのアプリケーションと互換性があり、それ以外では最小限の 書き換えですむこと。しかし、プリコンパイルを使用しているためにタイプ3のZK-EVMが削除されたり、エッジケースに微妙に依存しているために、VMの扱いが異なるために書き換えが必要になるアプリケーションもあります。
Scroll と Polygon 。PolygonはzkASMという独自の内部言語をZK検証しており、zkASMの実装を使ってZK-EVMのコードを解釈するという設計。
将来的には、タイプ1またはタイプ2のZK-EVMは、低いプロバー時間とガスコストで開発者に機能を提供する新しいZK-SNARKフレンドリーなプリコンパイルを追加することにより、自発的にタイプ3のZK-EVMになる可能性がある。
Type 4 (high-level-language equivalent)
タイプ4のシステムは、高位言語(例:Solidity、Vyper、または両者がコンパイルできる中間言語)で書かれたスマートコントラクトのソースコードを、ZK-SNARKフレンドリーに設計された言語にコンパイルすることで動作する。
これにより、EVMの各実行ステップの異なる部分をすべてZK-proveせず、直接高レベルコードから開始することで検証時間を短縮できる。また、証明者になることを容易にすることで分散化を助ける。
デメリット:非互換性が高くなる
VyperやSolidityで書かれた「普通の」アプリケーションはコンパイルすれば「普通に」動くが、多くのアプリケーションが「普通」ではない重要な点がいくつかあります。
コントラクトのアドレスはCREATE2の正確なバイトコードに依存するため、Type4システムでは、EVMと同じアドレスを持たないかもしれません。これは、まだ配備されていない「反実仮想契約」に依存するアプリケーション、ERC-4337ウォレット、EIP-2470シングルトンや他の多くのアプリケーションを壊してしまいます。
手書きEVMバイトコードは、より使いにくいです。多くのアプリケーションは、効率化のために手書きのEVMバイトコードを部分的に使用しています。タイプ4のシステムはこれをサポートしないかもしれませんが、完全なタイプ3のZK-EVMになる努力をせずに、これらのユースケースを満たすために限定的なEVMバイトコードサポートを実装する方法があります。
多くのデバッグインフラは EVM バイトコード上で動作するため、引き継ぐことができません。しかし、このデメリットは、「従来の」高級言語や中間言語(例:LLVM)からデバッグインフラにアクセスすることができるため、軽減されます。
cairoのような言語は必要ではないんだな
まとめるとこのようになる。いずれも劣後を論ずるのではなくトレードオフに目をむける必要がある。
さらに、ZK-EVMプロジェクトでは、高い番号のタイプから始めて、時間の経過とともに低い番号のタイプに移行する(またはその逆)ことができる。
https://scrapbox.io/files/63ac65af3ae150001ebdce91.png
これからのzkEVM
記事の中でビタリクは、ZK-EVMの改善とイーサリアム自体のZK-SNARKフレンドリー化の組み合わせによって、すべてが時間をかけてタイプ1になっていくことを望んでいる。
そのような未来では、ZK-EVMの実装が複数になり、ZKのロールアップとイーサリアムのチェーン自体の検証の両方に使用でき、理論的には、EthereumがL1用に単一のZK-EVM実装を標準化する必要はなく、異なるクライアントが異なる証明を使用できる。
コードの冗長性はあるが