著者:Wuyue、オタクウェブ3
ご存知のとおり、EVMはイーサリアムの「実行エンジン」および「スマートコントラクト実行環境」に位置付けられており、イーサリアムの最も重要なコアコンポーネントの1つと言えます。パブリック チェーンは、数千のノードを含むオープン ネットワークです。異なるノードのハードウェア パラメーターは大きく異なります。スマート コントラクトを複数のノードで実行して「一貫性」を満たしたい場合は、異なるデバイスで実行するようにする必要があります。すべてのプラットフォームで同じ環境が構築され、仮想マシンでこの効果を実現できます。
イーサリアムの仮想マシン EVM は、さまざまなオペレーティング システム (Windows、Linux、macOS など) およびデバイス上で同じ方法でスマート コントラクトを実行でき、このクロスプラットフォーム互換性により、コントラクトの実行後に各ノードが一貫した結果を得ることができます。最も典型的な例は、Java 仮想マシン JVM です。
通常、ブロック エクスプローラーで表示されるスマート コントラクトは、まず EVM バイトコードにコンパイルされてからチェーンに保存されます。 EVM がコントラクトを実行するとき、これらのバイトコードを順番に直接読み取ります。バイトコードに対応する各命令 (opCode) には、対応するガス コストがあります。 EVM は実行中の各命令のガス消費量を追跡します。消費量は操作の複雑さによって異なります。
さらに、EVM はイーサリアムのコア実行エンジンとして、シリアル実行を使用してトランザクションを処理します。すべてのトランザクションは単一のキューに入れられ、決められた順序で実行されます。並列化を行わない理由は、ブロックチェーンではトランザクションのバッチをすべてのノードで同じ順序で処理する必要があるため、トランザクション処理を並列化しないとトランザクションの順序を正確に予測することが困難になるためです。対応するスケジューリング アルゴリズムですが、これはより複雑になります。
2014 年から 2015 年にかけてイーサリアム創設チームは、時間の制約からシリアル実行方法を選択しました。シンプルでメンテナンスしやすいように設計されているためです。しかし、ブロックチェーン技術の反復とユーザーベースの拡大に伴い、ブロックチェーンの TPS とスループットの要件はますます高くなり、ロールアップ技術の出現と実装が成熟した後、EVM のシリアル実行によって引き起こされるパフォーマンスのボトルネックが明らかになりました。イーサリアムの第二層。
レイヤ 2 の主要なコンポーネントとして、シーケンサは単一サーバーの形式ですべてのコンピューティング タスクを実行します。シーケンサと連携する外部モジュールの効率が十分に高い場合、最終的なボトルネックはシーケンサ自体の効率に依存します。時間が経つと、連続実行が大きな障害になります。
opBNB チームは、DA 層とデータの読み取りおよび書き込みモジュールで極端な最適化を行い、1 秒あたり最大 2,000 回を超える ERC-20 転送を実行できます。この数値は高いように見えますが、処理されるトランザクションが ERC-20 転送よりもはるかに複雑な場合、TPS 値は必然的に大幅に減少します。したがって、トランザクション処理の並列化は今後避けられないトレンドとなります。
次に、より具体的な詳細から始めて、従来の EVM の制限と並列 EVM の利点を説明します。
Ethereum トランザクション実行の 2 つのコア コンポーネント
コード モジュール レベルでは、EVM に加えて、go-ethereum でのトランザクション実行に関連するもう 1 つのコア コンポーネントは stateDB です。これは、Ethereum でのアカウント ステータスとデータ ストレージを管理するために使用されます。 Ethereum は、Merkle Patricia Trie と呼ばれるツリー構造を使用してデータベース インデックス (ディレクトリ) として機能します。EVM の各トランザクション実行により、stateDB に保存されている特定のデータが変更され、最終的には Merkle Patricia Trie (以下、「Merkle Patricia Trie」と呼びます) に反映されます。グローバル状態ツリー)中央。
具体的には、stateDB は、EOA アカウントや契約アカウントを含むすべての Ethereum アカウントのステータスを維持する責任を負い、保存されるデータには、アカウント残高、スマート コントラクト コードなどが含まれます。トランザクション実行プロセス中に、stateDB は対応するアカウントのデータの読み取りと書き込みを行います。トランザクションの実行後、stateDB は永続化のために新しい状態を基礎となるデータベース (LevelDB など) に送信する必要があります。
一般に、EVM はスマート コントラクトの命令を解釈して実行し、計算結果に基づいてブロックチェーン上の状態を変更する責任を負い、stateDB はグローバルな状態ストレージとして機能し、すべてのアカウントとコントラクトの状態変更を管理します。両者は協力してイーサリアムのトランザクション実行環境を構築する。
シリアル実行の具体的なプロセス
イーサリアムには、EOA 送金と契約トランザクションという 2 種類のトランザクションがあります。 EOA 送金は最も単純なタイプのトランザクションであり、通常の口座間の ETH 送金です。この種のトランザクションにはコントラクト呼び出しが含まれず、非常に迅速に処理されます。操作が簡単なため、EOA 転送に請求されるガス料金は非常に低くなっています。
単純な EOA 転送とは異なり、コントラクト トランザクションにはスマート コントラクトの呼び出しと実行が含まれます。 EVM がコントラクト トランザクションを処理する場合、スマート コントラクト内のバイトコード命令を 1 つずつ解釈して実行する必要があります。コントラクトのロジックが複雑になればなるほど、必要な命令が増え、より多くのリソースが消費されます。
たとえば、ERC-20 転送の処理時間は EOA 転送の約 2 倍ですが、Uniswap でのトランザクション操作など、より複雑なスマート コントラクトの場合は時間がかかり、EOA 転送よりも 10 倍以上遅くなる場合もあります。これは、DeFiプロトコルが流動性プール、価格計算、取引中のトークンスワップなどの複雑なロジックを処理する必要があり、非常に複雑な計算を必要とするためです。
では、EVM と stateDB の 2 つのコンポーネントはどのように連携してシリアル実行モードでトランザクションを処理するのでしょうか?
イーサリアムの設計では、ブロック内のトランザクションは 1 つずつ順番に処理され、各トランザクション (tx) はトランザクションの特定の操作を実行するために使用される独立したインスタンスを持ちます。各トランザクションは異なる EVM インスタンスを使用しますが、すべてのトランザクションは同じ状態データベース (stateDB) を共有します。
トランザクション実行プロセス中、EVM は継続的に stateDB と対話し、stateDB から関連データを読み取り、変更されたデータを stateDB に書き戻す必要があります。
EVM と stateDB がどのように連携してトランザクションを実行するかをコードの観点から大まかに見てみましょう。
1. processBlock() 関数は、Process() 関数を呼び出して、ブロックに含まれるトランザクションを処理します。
2. Process() 関数内に for ループが定義されており、トランザクションが 1 つずつ実行されることがわかります。
3. すべてのトランザクションが処理された後、processBlock() 関数は writeBlockWithState() 関数を呼び出し、次に、statedb.Commit() 関数を呼び出して状態変更結果を送信します。
ブロック内のすべてのトランザクションが実行されると、stateDB 内のデータが前述のグローバル ステート ツリー (Merkle Patricia Trie) にコミットされ、新しいステート ルート (stateRoot) が生成されます。状態ルートは、各ブロックの重要なパラメータであり、ブロックの実行後の新しいグローバル状態の「圧縮結果」を記録します。
EVM のシリアル実行モードのボトルネックが明らかであることを理解するのは難しくありません。トランザクションは順番に実行するためにキューに入れられる必要があり、長時間かかるスマート コントラクト トランザクションがある場合、他のトランザクションはそれが処理されるまで待機することしかできません。 CPU やその他のハードウェア リソースを完全に活用できないことは明らかであり、効率は大幅に制限されます。
EVM 向けのマルチスレッド並列最適化ソリューション
実際の例を使用してシリアル実行とパラレル実行を比較すると、前者はカウンタが 1 つだけあるバンクに似ており、パラレル EVM は複数のカウンタを持つバンクに似ています。パラレルモードでは、複数のスレッドを起動して複数のトランザクションを同時に処理できるため、効率が数倍向上しますが、厄介な点はステータスの競合の問題です。
複数のトランザクションがアカウントのデータを書き換えることを宣言した場合、たとえば、1 つの NFT のみが鋳造でき、トランザクション 1 とトランザクション 2 の両方が鋳造することを宣言すると、競合が発生します。すべてのリクエストが満たされた場合、エラーが発生することは明らかであり、そのような状況に対処するには調整が必要です。実際の運用では状態競合が上記よりも頻繁に発生することが多いため、トランザクション処理を並列化する場合には状態競合への対策が必要です。
Reddio の EVM の並列最適化原理
ZKRollup プロジェクト Reddio の EVM に対する並列最適化のアイデアを見てみましょう。 Reddio のアイデアは、トランザクションを各スレッドに割り当て、pending-stateDB と呼ばれる一時的な状態データベースを各スレッドに提供することです。具体的な詳細は以下のとおりです。
1. マルチスレッドによるトランザクションの並列実行: Reddio は、複数のスレッドをセットアップして、スレッド間で干渉することなく、異なるトランザクションを同時に処理します。これにより、トランザクション処理が数倍高速化される可能性があります。
2. 一時状態データベースを各スレッドに割り当てる: Reddio は、独立した一時状態データベース (pending-stateDB) を各スレッドに割り当てます。各スレッドがトランザクションを実行するとき、グローバル stateDB は直接変更されませんが、状態変更の結果が一時的に pending-stateDB に記録されます。
3. 同期状態変更: ブロック内のすべてのトランザクションが実行された後、EVM は各 pending-stateDB に記録された状態変更結果をグローバル stateDB に順番に同期します。異なるトランザクションの実行中に状態の競合がない場合、pending-stateDB 内のレコードはグローバル stateDB に正常にマージできます。
Reddio は、トランザクションが状態データに正しくアクセスし、競合を回避できるように、読み取りおよび書き込み操作の処理方法を最適化しました。
·読み取り操作: トランザクションが状態を読み取る必要がある場合、EVM は最初に保留状態の ReadSet をチェックします。 ReadSet によって必要なデータが存在することが示された場合、EVM は pending-stateDB からデータを直接読み取ります。対応するキーと値 (キーと値のペア) が ReadSet 内に見つからない場合、履歴状態データは前のブロックに対応するグローバル stateDB から読み取られます。
·書き込み操作: すべての書き込み操作 (つまり、状態への変更) は、グローバル stateDB に直接書き込まれず、最初に保留状態の WriteSet に記録されます。トランザクションの実行が完了したら、競合検出を通じて状態変更の結果をグローバル stateDB にマージしようとします。
並列実行の主な問題は状態の競合です。これは、複数のトランザクションが同じアカウントの状態を読み書きしようとする場合に特に重大です。このため、Reddio では競合検出メカニズムを導入しています。
· 競合検出: トランザクションの実行中、EVM は異なるトランザクションの ReadSet と WriteSet を監視します。複数のトランザクションが同じステータス項目の読み取りまたは書き込みを試行していることが判明した場合、競合とみなされます。
· 競合処理: 競合が検出されると、競合するトランザクションは再実行が必要であるとマークされます。
すべてのトランザクションが実行された後、複数の pending-stateDB 内の変更レコードがグローバル stateDB にマージされます。マージが成功すると、EVM は最終状態をグローバル状態ツリーにコミットし、新しい状態ルートを生成します。
マルチスレッド並列最適化によるパフォーマンスの向上は、特に複雑なスマート コントラクト トランザクションを処理する場合に顕著です。
並列 EVM の調査によると、低競合ワークロード (トランザクション プール内の競合トランザクションが少ない、または同じリソースを占有するトランザクション) では、ベンチマーク テストの TPS が従来のシリアル実行と比較して約 3 ~ 5 倍向上します。競合の多いワークロードでは、すべての最適化方法を使用した場合、理論的には 60 回に達することもあります。
要約する
Reddio の EVM マルチスレッド並列最適化ソリューションは、各トランザクションに一時的な状態ライブラリを割り当て、異なるスレッドでトランザクションを並列実行することにより、EVM のトランザクション処理機能を大幅に向上させます。 EVM ベースのパブリック チェーンは、読み取りおよび書き込み操作を最適化し、競合検出メカニズムを導入することで、状態の一貫性を確保しながらトランザクションの大規模な並列化を実現し、従来のシリアル実行モードによって引き起こされるパフォーマンスのボトルネックを解決します。これは、イーサリアム ロールアップの将来の開発のための重要な基盤を築きます。
フォローアップでは、ストレージ効率の最適化によって効率をさらに向上させる方法、競合が多い場合の最適化ソリューション、最適化のための GPU の使用方法など、Reddio の実装の詳細をさらに分析します。