TL;DR
仮想マシンは、プログラムに実行環境を提供するソフトウェアシミュレーションのコンピュータシステムです。さまざまなハードウェアデバイスをシミュレートし、プログラムを制御された互換性のある環境で実行できます。イーサリアム仮想マシン(EVM)は、イーサリアムスマートコントラクトを実行するためのスタックベースの仮想マシンです。zkEVM は、ゼロ知識証明 / 有効性証明技術を統合した EVM です。これにより、すべての検証者が EVM を再実行することなく、ゼロ知識証明を使用して EVM の実行プロセスを検証できます。市場にはさまざまな zkEVM 製品があり、それぞれ独自の方法と設計を持っています。zkEVM が必要な理由は、Layer 2 でのスマートコントラクト実行をサポートする仮想マシンの需要にあります。また、一部のプロジェクトは、EVM の広範なユーザーエコシステムを活用し、ゼロ知識証明によりフレンドリーな命令セットを設計するために zkEVM を選択しています。Kakarot は、Cairo 言語を使用して Starknet 上に実装された zkEVM です。これは、Cairo スマートコントラクトの形式で EVM のスタック、メモリ、実行などをシミュレートしています。Kakarot は、Cairo 言語がまだ実験段階にあるため、Starknet アカウントシステムとの互換性、コスト最適化、安定性などの課題に直面しています。Warp は、Solidity コードを Cairo コードに変換するコンバータであり、高級言語レベルでの互換性を提供します。一方、Kakarot は EVM のオペコードとプリコンパイルを実装することで、EVM レベルでの互換性を提供します。
何が仮想マシンなのか?
仮想マシンが何であるかを明確にするためには、まず現在の主流であるフォン・ノイマンアーキテクチャに基づくコンピュータの実行プロセスについて説明する必要があります。コンピュータ上で実行されるさまざまなプログラムは、通常、高級言語を段階的に変換し、最終的に機械が理解できる機械コードを生成して実行されます。機械コードへの変換方法によって、高級言語は大きくコンパイラ型言語とインタプリタ型言語に分けられます。
コンパイラ型言語は、コードの記述が完了した後、コンパイラによって処理され、高級言語コードが機械コードに変換され、実行可能ファイルが生成されます。一度コンパイルすれば、何度も高効率で実行できます。コンパイラ型言語の利点は、コンパイル時にコードが機械コードに変換されているため、実行速度が速く、コンパイラのない環境でもプログラムを実行でき、ユーザーが使用しやすく、追加のソフトウェアをインストールする必要がないことです。一般的なコンパイラ型言語には C、C++、Go などがあります。
コンパイラ型言語に対して、インタプリタ型言語があります。インタプリタ型言語は、コードがインタプリタによって逐次的に解釈され、コンピュータ上で直接実行され、毎回実行時に再翻訳プロセスが必要です。インタプリタ型言語の利点は、開発効率が高く、コードのデバッグが容易ですが、実行速度は相対的に遅くなります。一般的なインタプリタ型言語には Python、JavaScript、Ruby などがあります。
言語は本質的にコンパイラ型とインタプリタ型を区別するものではなく、初期設計時にいくつかの傾向があるだけです。C/C++ はほとんどの場合コンパイル実行されますが、インタプリタ実行も可能です(Cint、Cling)。多くの伝統的なインタプリタ型言語は、現在は中間コードにコンパイルされ、仮想マシン上で実行されています(Python、Lua)。物理マシンの実行プロセスを理解した上で、仮想マシンについて説明します。
仮想マシンは、異なるハードウェアデバイスをシミュレートすることで仮想的なコンピュータ環境を提供します。異なる仮想マシンがシミュレートできるハードウェアデバイスは異なりますが、通常は CPU、メモリ、ハードディスク、ネットワークインターフェースなどが含まれます。
イーサリアム仮想マシン EVM を例に挙げると、EVM はスタックベースの仮想マシンであり、イーサリアムスマートコントラクトを実行するために使用されます。EVM は CPU、メモリ、ストレージ、スタックなどのハードウェアデバイスをシミュレートすることで、仮想的なコンピュータ環境を提供します。
具体的には、EVM はスタックベースの仮想マシンであり、データと命令を実行するためにスタックを使用します。EVM の命令セットには、算術操作、論理操作、ストレージ操作、ジャンプ操作などのさまざまなオペコードが含まれており、これらの命令は EVM のスタック上で実行され、スマートコントラクトの実行を完了します。
EVM がシミュレートするメモリとストレージは、スマートコントラクトの状態とデータを保存するためのデバイスです。EVM はメモリとストレージを 2 つの異なる領域として扱い、メモリとストレージを読み書きすることでスマートコントラクトの状態とデータにアクセスできます。
EVM がシミュレートするスタックは、命令のオペランドと結果を保存するために使用されます。EVM の命令セットのほとんどの命令はスタックベースであり、スタックからオペランドを読み取り、結果をスタックにプッシュします。
要するに、EVM は CPU、メモリ、ストレージ、スタックなどのハードウェアデバイスをシミュレートすることで仮想的なコンピュータ環境を提供し、スマートコントラクトの命令を実行し、スマートコントラクトの状態とデータを保存します。実際の実行では、EVM はスマートコントラクトのバイトコードをメモリにロードし、命令セットを実行してスマートコントラクトのロジックを実行します。EVM が実際に置き換えるのは、上の図のオペレーティングシステム + ハードウェアの部分です。
EVM の設計プロセスは明らかにボトムアップであり、最初にシミュレートするハードウェア環境(スタック、メモリ)を決定し、それに基づいて独自のアセンブリ命令セット(Opcode)とバイトコード(Bytecode)を設計しました。アセンブリ命令セットは人間が見るためのものですが、底層の知識が多く関与しており、開発者に高い要求があり、開発が煩雑になるため、高級言語が必要であり、難解で煩雑な底層呼び出しを隠蔽し、開発者により良い体験を提供します。EVM はそのアセンブリ命令セットのカスタマイズ設計により、従来の高級言語を直接利用することが難しく、新しい高級言語を再設計してこの仮想マシンに適合させました。イーサリアムコミュニティは、EVM の実行効率のために 2 つのコンパイラ型高級言語 —Solidity と Vyper を設計しました。Solidity は言うまでもなく、Vyper は Vitalik が Solidity の一部の欠陥を改善するために設計した EVM 高級言語ですが、コミュニティではあまり採用されず、次第に歴史の舞台から姿を消しました。
何が zkEVM か
簡単に言えば、zkEVM はゼロ知識証明 / 有効性証明技術を利用した EVM であり、EVM の実行プロセスをゼロ知識証明 / 有効性証明を通じてより効率的かつ低コストで検証できるようにします。すべての検証者が EVM の実行プロセスを再実行する必要はありません。
市場には多くの zkEVM 製品があり、競争が激しく、主要なプレイヤーには Starknet、zkSync、Scroll、Taiko、Linea、Polygon zkEVM(旧 Polygon Hermez)などがあり、Vitalik によって 5 つのカテゴリ(1、2、2.5、3、4)に分けられています。具体的な内容は Vitalik のブログを参照してください。
なぜ zkEVM が必要なのか
この問題は 2 つの側面から見る必要があります。
最初の zk Rollup の試みは、比較的単純な送金や取引機能しか実現できませんでした。例えば、zkSync Lite や Loopring などです。しかし、かつての海は水ではない、イーサリアム上のチューリング完全な EVM に慣れた人々は、プログラミングによって多様なアプリケーションを創造できないとき、L2 上の仮想マシンを求め始めました。スマートコントラクトを書く必要があるのです。
EVM の一部の設計がゼロ知識証明 / 有効性証明の生成に対して友好的でないため、一部のプレイヤーは、底層でゼロ知識証明 / 有効性証明に友好的な命令セットを使用することを選択しました。例えば、Starknet の Cairo Assembly や zkSync の Zinc Instruction などです。しかし、皆が EVM の巨大なユーザーエコシステムを放棄したくないため、上層で EVM と互換性を持つことを選択しました。これが 3、4 類の zkEVM です。また、一部のプレイヤーは EVM の従来の命令セット Opcode を維持し、Opcode のためにより効率的な証明を生成することに注力しています。これが 1、2 類の zkEVM です。EVM の巨大なエコシステムが必要です。
Kakarot:仮想マシン上の仮想マシン?
なぜ仮想マシン上にさらに仮想マシンを作ることができるのでしょうか?これはコンピュータ業界の人々にとっては当たり前のことですが、コンピュータを理解していないユーザーにはそれほど明白ではないかもしれません。実際、これは非常に理解しやすいことで、積み木を積むようなもので、下層が十分に堅固であれば(チューリング完全な実行環境がある)、無限に上層に積み木を重ねることができます。しかし、何層積み重ねても、最終的な実行は最下層の物理ハードウェアに処理される必要があるため、層数が増えると効率が低下します。また、異なる積み木の設計が異なるため(仮想マシンの設計が異なる)、積み木が高くなるにつれて、積み木が崩れる可能性が高くなります(実行エラーが発生する)ので、より高い技術レベルが必要です。
Kakarot は、Starknet 上で Cairo 言語を使用して実装された EVM であり、Cairo スマートコントラクトの形式で EVM のスタック、メモリ、実行などをシミュレートしています。相対的に、EVM を実装することはそれほど難しくありません。最も使用されている Go-Ethereum で Golang で書かれた EVM を除いて、現在は Python、Java、JavaScript、Rust で書かれた EVM も存在します。
Kakarot zkEVM の技術的な難しさは、プロトコルが Starknet チェーン上のコントラクトとして存在するため、2 つの重要な問題を引き起こすことです。
互換性:Starknet はイーサリアムとは完全に異なるアカウントシステムを使用しています。イーサリアムではアカウントは EOA(外部所有アカウント)と CA(コントラクトアカウント)に分かれていますが、Starknet ではネイティブのアカウント抽象をサポートしており、すべてのアカウントがコントラクトアカウントです。また、使用される暗号アルゴリズムが異なるため、ユーザーは同じエントロピーを使用して Starknet でイーサリアムと同じアドレスを生成することができません。
コスト:Kakarot zkEVM はチェーン上のコントラクトとして存在するため、コード実装には高い要求があり、可能な限り Gas に最適化し、インタラクションコストを削減する必要があります。
安定性:Golang、Rust、Python などの従来の高級言語とは異なり、Cairo 言語はまだ実験段階にあり、Cairo 0 から Cairo 1、さらに Cairo 2(またはお好みで Cairo 1 version 2)へと、公式チームは言語の特性を継続的に修正しています。また、Cairo VM は十分なテストを受けておらず、今後大規模な書き換えの可能性も排除できません。
Kakarot プロトコルは、5 つの主要なコンポーネントで構成されています(GitHub ドキュメントでは 4 つと記載されていますが、EOA が含まれていないため、読者の理解を助けるために調整しました):
Kakarot (Core):イーサリアム形式のトランザクションを実行し、イーサリアムユーザーに対応する Starknet アカウントを提供します。
Contract Accounts:イーサリアムの CA に相当し、コントラクトのバイトコードやコントラクト内の変数の状態を保存します。
Externally Owned Accounts:イーサリアムの EOA に相当し、イーサリアムのトランザクションを Kakarot Core に転送します。
Account Registry:イーサリアムアカウントと Starknet アカウントの対応関係を保存します。
Blockhash Registry:Blockhash は特別な Opcode として、過去のブロックデータが必要ですが、Kakarot はチェーン上で直接データを取得できません。このコンポーネントは block_number -> block_hash のマッピングを保存し、管理者が書き込み、Kakarot Core に提供します。
Kakarot の CEO である Elias Tazartes のフィードバックによると、チームの最新バージョンでは、Account Resister の設計を放棄し、直接 31 バイトの Starknet アドレスを 20 ビットの EVM アドレスにマッピングして対応関係を保存することに変更しました。将来的には、相互運用性を向上させ、Starknet コントラクトが独自の EVM アドレスを登録できるようにするために、Account Register の設計を再度使用する可能性があります。
Starknet 上で EVM と互換性を持つ:Warp と Kakarot の違い
Vitalik が定義した zkEVM のタイプに従うと、Warp は Type-4 に該当し、Kakarot は現在 Type-2.5 に該当します。
Warp は Solidity コードを Cairo コードに変換するトランスパイラであり、コンパイラとは呼ばれないのは、出力される Cairo が依然として高級言語であるためです。Warp を使用することで、Solidity 開発者は元の開発状態を維持し、新しい Cairo 言語を学ぶ必要がありません。多くのプロジェクトにとって、Warp は Starknet エコシステムへの参入障壁を下げ、大量のエンジニアリングコードを Cairo で書き直す必要がありません。
トランスパイルの考え方はシンプルですが、互換性は最も低く、一部の Solidity コードは Cairo にうまく翻訳できず、アカウントシステムや暗号アルゴリズムなどのコードロジックを変更する必要があります。具体的なサポートされていない特徴は Warp のドキュメントに記載されています。例えば、多くのプロジェクトは EOA アカウントとコントラクトアカウントの実行ロジックを区別しますが、Starknet ではすべてのアカウントがコントラクトアカウントであるため、この部分のコードは変更後にトランスパイルする必要があります。
Warp は高級言語レベルでの互換性を提供し、Kakarot は EVM レベルでの互換性を提供します。
EVM の完全な書き換え、Opcode とプリコンパイルの逐条実装により、Kakarot はより高いネイティブ互換性を持っています。結局のところ、同じ仮想マシン(EVM)内で実行する方が、異なる仮想マシン(Cairo VM)内で実行するよりも常に互換性があります。Account Registry や Blockhash Registry は、異なるシステム間の違いを巧妙に隠蔽し、ユーザーの移行摩擦を最小限に抑えています。
Kakarot チーム
Kakarot チームに感謝し、特に Elias Tazartes に貴重な意見をいただきました。ありがとうございます!