翻訳: Anza's New SVM API
この記事はSolana Advent Calendar 2024の 8日目の記事です。
本記事ではSVM APIについて解説したJoe Caulfield氏のAnza's New SVM API - Anzaの簡易翻訳記事です。このSVM APIが最近の僕の中で熱い技術なのでこの機会に紹介を兼ねて翻訳します。
Anzaの新しいSVM API
Solanaは現在、"SVM" (Solana Virtual Machine) の登場により、独自の"EVM"モーメントを経験しています。2022年のEthereumと同様に、数多くの"SVM"プロジェクトが、Solanaの高度なトランザクション処理能力を活用して、Solanaバリデータを超えたさまざまなアプリケーションを実現するための野心的な取り組みを開始しています。
SVMエコシステムが急速に拡大する中、開発者やイノベーターは新たな可能性を探求し、この強力なテクノロジーで達成可能なことの限界を押し広げています。しかし、SVMとは一体何であり、どのようにプロジェクトを構築できるのでしょうか?
SVMの定義
Solanaエコシステム内のエンジニアは、Solana Virtual Machineの正確な定義についてさまざまな見解を持っています。一部の人々は、それがバリデータランタイムからプログラム実行まで、トランザクション処理パイプライン全体を包含していると主張しています。他の人は、真のSVMは単にプログラムの実行を担当する低レベルのeBPF仮想マシンであると考えています。
ほとんどの新興SVMプロジェクトは、Solana Virtual Machineのより広範な視点である前者の見方を支持しているようです。このことを念頭に置いて、トランザクション処理パイプラインを分解し、その構成要素を理解することが重要になります。
AgaveバリデータのBankコンポーネントは、バリデータ内のSVMのオーケストレーターとして機能します。Bankは、バリデータランタイムの大部分を包含し、特定のスロットでのネットワークの状態管理を担当します。スロットは異なるフォークに存在する可能性がありますが、この複雑さはSVMの範囲を超えています。
Solanaネットワークが稼働すると、トランザクションはネットワーク接続を介してバリデータに送信され、その後、実行のためにランタイムにルーティングされます。特定のスロットの間、そのスロットのBankはトランザクションを処理し、それらをブロックに詰め込むことを試みます。
Solanaプロトコルは、トランザクションをリーダースケジュール内の次のリーダーに転送します。つまり、保留中のトランザクションのためにmempoolを利用しません。リーダーが現在のスロットにトランザクションを含めることができない場合、そのトランザクションは次のリーダーに転送されます。リーダーはBankを使用してブロックをパッキングし、他のノードはブロックをリプレイして、Bankの一致するインスタンスを再構築し、ブロックの有効性を検証しようとします。
ノードがブロックのパッキング(リーダー)を行うか、ブロックのリプレイ(バリデータ)を行うかに関係なく、トランザクションはバッチ処理されます。各トランザクションには1つ以上の命令が含まれており、各命令は特定のプログラムを対象としています。
上の図に示すように、命令にはアカウントのロードと書き込みロックの決定に関連する情報が含まれています。読み取り専用アカウントと「書き込み可能」アカウントのこの概念により、Bankインスタンス間でのアカウントデータへの並列アクセスが可能になります。
トランザクションが処理される前に、「サニタイゼーション」プロセスを経て、さまざまなチェックが行われ、命令から処理情報が抽出されます。サニタイゼーション中に有用な最適化の1つは、トランザクションの命令からアカウントキーの抽出と重複排除です。これにより、SVMはトランザクション全体に必要なキーを重複や不必要な労力なしにロードできます。
すべてのアカウントがロードされると、SVMは各命令の実行可能プログラムをロードし、eBPF仮想マシンをプロビジョニングしてプログラムを実行し、結果を返します。バイトコードからマシンコードへの冗長な変換を避けるために、キャッシュメカニズムが使用されます。このキャッシュメカニズムは、変換されたプログラムを絶対に再計算する必要があるまで(またはキャッシュがいっぱいになるまで)保存します。
このエンドツーエンドの複雑さのすべては、SVMコンポーネント内で発生し、Bankによって駆動されます。Bankによって使用されるSVMインターフェースはBankから大幅に切り離されており、この新しい、切り離された、明確に定義されたSVMインターフェースを取り巻く多くの興味深い機会につながります。主に、これはSVMが他のコンポーネントによって、Solanaバリデータの外側から駆動されることを意味します。
SVMの機会
SVMのアーキテクチャを包括的に理解することで、このスタンドアロンソフトウェアコンポーネントが何に使用できるのかを理解することが重要になります。スタンドアロンで構成可能なSVMには、Solanaバリデータノードの内外に多くの機会が存在します。以下は、最も一般的な例のいくつかです。
オフチェーンサービス: SVMを使用して、Solanaのトランザクション処理プロトコルをエミュレートするが完全にオフチェーンで動作するサービスを構築できます。これは、トランザクションのシミュレーションやファジング/テストなどに役立ちます。実際、このアーキテクチャは、今後のRPC v2での大きなブレークスルーにつながる可能性があります。
ダイエットクライアント: SVMは、スーパーマジョリティによる無効な状態遷移を実証するための不正証明の作成を可能にします。これにより、軽量クライアントは、すべてのトランザクションを処理したり、完全なブロックチェーン状態を維持したりする必要なく、効率的に動作できます。不正証明に依存することで、ダイエットクライアントはネットワークの整合性を確保し、最小限のリソース要件でトランザクションの有効性を検証できます。これにより、スケーラビリティとセキュリティが向上します。SIMD 0065を参照してください。
ステートチャンネル: プロジェクトはSVMベースのステートチャンネルを構築できます。ステートチャンネルは、さまざまなエキサイティングで創造的なユースケースを可能にします。ステートチャンネルを使用すると、プロトコルはネットワーク内で許可されるトランザクションの種類を制限し、接続を厳密にピアツーピアまたはパーティベースに制限することを選択できます。チャンネルが最終的にクローズされると、チャンネルのトランザクションの最終結果はメインチェーンに投稿されます。古典的な例はトークン支払いチャンネルであり、1つ以上のトークンがサポートされ、チャンネル参加者の最終的な残高が投稿されます。
ロールアップ: 完全なバリデータまたはコンセンサプロトコルなしでトランザクションまたはブロックを実行する必要があるネットワークは、SVMを利用してロールアップを構築できます。ロールアップは、SVMを実行レイヤーとして使用し、ロールアップ内の状態遷移の「証明」をメインチェーンに決済します。このアーキテクチャは、SVMの実行を並行して実行できるため、大幅なスケーリングの可能性を提供します。
Avalancheサブネット: 隔離されたSVM実行レイヤーは、Avalancheサブネット内で使用でき、コンセンサスとネットワークのためにAvalancheモジュールに依存します。
拡張SVM: SVMは、カスタムのプロトコル準拠の機能で拡張できます。これらの「拡張」SVMユニットは、Solanaバリデータまたは上記のソリューションのいずれかにプラグインできます。
AnzaのSVMの主なアプリケーションは、Agaveバリデータ内のトランザクション処理です。ただし、前述のように、SVMインターフェースはバリデータランタイムから切り離され、公式仕様を通じて利用可能になりました。
この自己完結型のSVMは、トランザクション処理とプログラム実行のすべての複雑な詳細を包含し、新しくリリースされたsolana-svm Rustクレート内にカプセル化されています。このライブラリは、切り離されたインターフェースを備えており、汎用性と構成可能なSVMユニットを提供し、前述のユースケースなどをサポートできます。
AnzaのSVM API
Anzaの新しいsolana-svm Rustクレートは、開発者に、Solanaメインネットベータ上でライブで動作するコンポーネントを使用してSVMプロジェクトを構築するために必要なツールを提供します。これにより、スタック全体が実戦テストされ、プロトコルに準拠していることが保証されます。さらに、パフォーマンスのために綿密に調整されており、ネットワークの成熟に伴って引き続き最適化されます。
SVM APIの詳細を以下に示します。SVMの中心的なインターフェースはTransactionBatchProcessor構造体に関係しています。
pub struct TransactionBatchProcessor<FG: ForkGraph> {
/// Bank slot (i.e. block)
slot: Slot,
/// Bank epoch
epoch: Epoch,
/// SysvarCache is a collection of system variables that are
/// accessible from on chain programs. It is passed to SVM from
/// client code (e.g. Bank) and forwarded to the MessageProcessor.
pub sysvar_cache: RwLock<SysvarCache>,
/// Programs required for transaction batch processing
pub program_cache: Arc<RwLock<ProgramCache<FG>>>,
/// Builtin program ids
pub builtin_program_ids: RwLock<HashSet<Pubkey>>,
}
これらのバッチプロセッサオブジェクトの1つをインスタンス化すると、アプリケーションは、以前のセクション(BPF Loader、eBPF VMなど)で示されたすべてのAgaveコンポーネントを使用して、サニタイズされたSolanaトランザクションのバッチを処理できるようになります。
トランザクションバッチを処理するためのメインAPIメソッドはload_and_execute_sanitized_transactionsです。次の引数が必要です。
callbacks: トランザクションプロセッサがアカウントに関する情報を呼び出し、特にトランザクション実行のためにアカウントをロードできるようにするTransactionProcessingCallbackトレイトインスタンス
sanitized_txs: サニタイズされたSolanaトランザクションのリスト
check_results: トランザクションチェック結果のリスト
environment: トランザクションバッチ処理のランタイム環境
config: トランザクション処理動作のカスタマイズのための設定
このメソッドはLoadAndExecuteSanitizedTransactionsOutputを返し、これは以下でより詳細に定義されています。
トランザクション処理コールバック
SVMの下流のコンシューマは、TransactionProcessingCallbackトレイトを実装して、トランザクションプロセッサにアカウントのロードやその他の関連情報の取得機能を提供する必要があります。
pub trait TransactionProcessingCallback {
fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData>;
fn account_matches_owners(&self, account: &Pubkey, owners: &[Pubkey]) -> Option<usize>;
fn add_builtin_account(&self, _name: &str, _program_id: &Pubkey) {}
}
APIがトレイト実装を受け入れるため、コンシューマはアカウントのロード、キャッシングなどに対して独自のカスタム実装を提供できます。この柔軟性により、プロジェクトはトランザクションプロセッサを特定のニーズに合わせて調整し、パフォーマンスとリソース管理を最適化できます。これらのカスタマイズ可能なトレイトを活用することで、開発者はアプリケーションの機能と効率を向上させ、SVMとのシームレスな統合を確保しながら、重要なプロセスに対する完全な制御を維持できます。
トランザクション処理環境
トランザクションプロセッサは、コンシューマにTransactionProcessingEnvironmentオブジェクトを介して、トランザクション処理に使用するランタイム環境を記述する値を提供する必要があります。
blockhash: トランザクションバッチに使用するブロックハッシュ。
epoch_total_stake: 現在のエポックの総ステーク。
epoch_vote_accounts: 現在のエポックの投票アカウント。
feature_set: トランザクションバッチに使用するランタイム機能セット。
lamports_per_signature: トランザクションごとに課金される署名あたりのランプート数。
rent_collector: トランザクションバッチに使用するレントコレクター。
これらの環境設定により、トランザクションに対して正確かつ制御された実行コンテキストが可能になり、特定の運用基準に準拠することが保証されます。これらのパラメータを構成することで、開発者はさまざまなトランザクション処理環境をエミュレートして、特定の要件を満たし、パフォーマンスを最適化し、ネットワークの整合性を維持できます。
トランザクション処理設定
コンシューマは、TransactionProcessingConfig引数を通じて、トランザクションプロセッサのデフォルト動作を調整するためのさまざまな設定を提供できます。
account_overrides: オーバーライドされたアカウントをカプセル化し、通常はトランザクションシミュレーションに使用されます。
compute_budget: トランザクション実行に使用する計算予算。
log_messages_bytes_limit: ログメッセージが消費できるバイト数の最大値。
limit_to_load_programs: トランザクションバッチにロードするプログラムの数を制限するかどうか。
recording_config: トランザクション実行の記録機能。
transaction_account_lock_limit: トランザクションがロックできるアカウントの最大数。
これらの設定により、開発者は全体的な環境を変更せずに、トランザクションプロセッサの特定の動作を微調整できます。これらのパラメータを調整することで、開発者はログ制限、計算リソースの割り当て、アカウント処理などの動作を制御し、トランザクションプロセッサが効率的に動作し、アプリケーションの特定のニーズを満たすことを保証できます。
トランザクション処理出力
トランザクションプロセッサのメインAPIメソッドであるload_and_execute_sanitized_transactionsは、処理されたトランザクションバッチの結果をカプセル化したLoadAndExecuteSanitizedTransactionsOutputオブジェクトを返します。
error_metrics: 処理されたトランザクションのエラーメトリクス。
execute_timings: トランザクションバッチ実行のタイミング。
execution_results: トランザクションが実行されたかどうかを示す結果のリスト。
loaded_transactions: 処理されたロードされたトランザクションのリスト。
追加のヘルパーとAPIメソッド
開発者は、MessageProcessor API(主にMessageProcessor::process_message)を使用して、トランザクションバッチの処理をバイパスすることもできます。これにより、アプリケーションはトランザクションメッセージをバッチではなく直接処理できますが、少し多くの設定が必要です。
さらに、いくつかのパブリックヘルパーが利用可能です。
account_loader::collect_rent_from_account: レントがまだ有効な場合、アカウントからレントを回収します。
account_loader::validate_fee_payer: ペイヤーアカウントがトランザクション手数料を支払うことができるかどうかをチェックします。
account_rent_state::RentState: アカウントのレント状態(レント支払い、レント免除など)を操作するためのAPI。
nonce_info: トランザクションノンスを操作するためのトレイトと構造体を含むモジュール。
program_loader::load_program_with_pubkey: パブリックキーでプログラムをロードします。
将来の展望
Solanaネットワークの成熟と、これらのエキサイティングな新しいSVMプロジェクトを取り巻くコミュニティの成長に伴い、Solana Virtual Machineは引き続き進化し続けるでしょう。バリデータの外部でのSVMの使用から、より高いパフォーマンスとより高い構成可能性が求められる新たなユースケースが生じるでしょう。
さらに、SVMプロジェクトの急増により、Solanaツールの新時代が到来しています。多くのチームが、プロジェクトのニーズに合わせてSVMをカスタマイズするカスタムソフトウェアソリューションを開発するだけでなく、ブリッジング、決済、プルーフなどの分野における画期的な技術を含む、まったく新しいテクノロジーを開発します。
業界全体は、AnzaのSVM APIと同様のオープンソースで利用可能なツールの共同開発から大きな利益を得るでしょう。この新しいSVMチームのエコシステムは、可能な限り協力してイノベーションを促進し、SVMの可能性の限界を押し広げるべきです。