新着:HeliusがLight Protocolを買収
Solana v1.18アップデート
ブログ/更新情報

Solana v1.18アップデートについて知っておくべきこと

Developer Experience EngineerXの0xIchigoLinkedInの0xIchigoGitHubの0xIchigo
読了時間:19分

この記事をレビューしてくださったRex St. John氏とMike MacCana氏に心より感謝します。

はじめに

Solanaの1.18アップデートが圧倒的多数に採用されたことは、重要な節目です。このアップデートでは、ネットワークのパフォーマンス、信頼性、効率性を高めるための多数の改善と新機能が導入されます。なかでも特に注目すべき変更が、中央スケジューラーの導入です。この新しいスケジューラーは、トランザクション処理を効率化し、優先順位をより正確かつ効率的に計算することを目的としています。また、ランタイム環境やプログラムのデプロイに対する改善により、ネットワーク負荷がピークに達している場合でも、より安定したパフォーマンスを実現できます。

この記事では、1.18リリースによってもたらされたアップデートと改善点を解説します。これらの変更に至った背景、新機能の詳細、ネットワーク改善への期待される効果を掘り下げます。バリデーター運用者、開発者、一般的なSolanaユーザーのいずれであっても、この1.18アップデートの包括的な概要を通じて、新しい改善点を理解し、そのメリットを活用するために必要な情報を得られます。

まず、これらの変更を推進するために新設された開発企業Anzaと、Solanaの継続的な開発における同社の役割について説明します。

Anzaとは?

Anzaは、Solana Labsの元経営陣とコアエンジニアによって新設されたソフトウェア開発企業です。その設立は、Solanaエコシステムを強化するための戦略的な取り組みであり、信頼性、分散性、ネットワークの堅牢性の向上を目指しています。Anzaは、重要なインフラの開発、主要プロトコルへの貢献、新しいツールのイノベーション促進を通じて、Solanaエコシステムを強化するために設立されました。

創業チームには、Jeff Washington、Stephen Akridge、Jed Halfon、Amber Christiansen、Pankaj Garg、Jon Cinqueの各氏と、Solana Labsの複数のコアエンジニアが名を連ねています。

Anzaは、Solana LabsバリデータークライアントのフォークであるAgaveを開発し、Solanaのバリデータークライアントの改良に注力しています。Anzaの目標は自社のバリデータークライアント開発にとどまらず、エコシステム全体の改善にも取り組んでいます。これには、Token ExtensionsやカスタマイズされたRust / Clangツールチェーンの開発も含まれます。Anzaは、協調的でオープンな開発アプローチを促進することで、Solanaエコシステムの成長を加速し、改善することに尽力しています。

Agaveとは?

前のセクションで簡単に触れたとおり、AgaveはAnzaが主導するSolana Labsバリデータークライアントのフォークです。ここでいう「フォーク」とは、Anzaの開発チームがSolana Labsのリポジトリから既存のコードを引き継ぎ、元のコードベースとは別の新しい開発経路を開始することを指します。これにより、AnzaはSolana Labsクライアントに独自の改善、機能、最適化を実装できます。

移行プロセス

クライアントのAnzaのGitHub組織への移行は、3月1日に開始されました。当初、Agaveはコミュニティが適応する時間を確保できるよう、Solana Labsのリポジトリをミラーリングします。この期間中、Anzaはプルリクエスト(PR)のクローズと、関連するissueのAgaveリポジトリへの移行を担当します。AgaveとSolana Labsクライアントのバージョン1.17および1.18は、機能面では同一です。Anzaは今夏にAgave v2.0をリリースする予定です。これに伴いSolana Labsクライアントはアーカイブされ、ネットワーク全体に新しいAgaveクライアントへの完全移行が推奨されます。

Solana LabsからAgaveへの移行プロセスは、GitHubで公開追跡されています。

Agave Runtime

Agave Runtimeは、その基盤アーキテクチャをSolana Virtual Machine(SVM)から継承しており、Sealevelランタイムによって定義される中核機能を実行する基盤です。 

Solanaプロトコルでは、ランタイムを、トランザクションの処理とアカウントデータベース内の状態更新を担う重要なコンポーネントとして定義しています。この仕様は、AgaveおよびFiredancerクライアントに採用され、さらに改良されています。SVMの本質は、すべてのSolanaプログラムを実行し、アカウントの状態を並列で変更できる点にあります。

バンクの概念は、トランザクション処理と1.18で導入される変更を理解するうえで重要です。バンクは、ロジックの一部であると同時に、特定時点における台帳の状態を表すものです。これは、アカウントデータベースを管理する高度なコントローラーとして機能し、クライアントアカウントの追跡、プログラム実行の管理、Solana台帳の整合性と進行の維持を担います。バンクは、特定のブロックに含まれるトランザクションから生じた状態を内包し、その時点における台帳のスナップショットとして機能します。

各バンクにはトランザクションの実行に必要なキャッシュと参照が備わっており、以前のスナップショットまたはジェネシスブロックから初期化できます。バリデーターがトランザクションを処理するBanking Stageでは、バンクを使用してブロックを組み立て、後からその整合性を検証します。このライフサイクルには、アカウントの読み込み、トランザクションの処理、状態を確定するためのバンクの凍結、そして最終的にルート化して永続性を確保する処理が含まれます。

概略として、Agave Runtime内のトランザクション処理エンジンは、プログラムの読み込み、コンパイル、実行を担います。Just-In-Time(JIT)コンパイルを使用し、コンパイル済みプログラムをキャッシュすることで、実行効率を最適化し、不要な再コンパイルを減らします。プログラムはデプロイ前にeBPF形式へコンパイルされます。その後、ランタイムはrBPFツールキットを使用してeBPF仮想マシンを作成します。この仮想マシンは、eBPFからx86_64マシンコード命令へのJITコンパイルを実行し、利用可能なハードウェアを最大限に活用します。これにより、プログラムを効率的に実行できます。

1.18アップデートでは、Agave Runtimeによって実現される運用効率と密接に関わる中央トランザクションスケジューラーが導入されます。1.18アップデートは、バンクを介したトランザクションのコンパイル、実行、管理方法を改善することで、より合理的で効率的なスケジューリングプロセスを実現します。その結果、トランザクション処理時間が短縮され、スループットが向上します。新しいAgave Runtimeとそのクライアントは、これらの改善の基盤です。そのため、新しいスケジューラーの詳細に踏み込む前に、概要を理解しておくことが重要です。 

Agave Runtimeについてさらに詳しく知りたい場合は、Joe Caulfield氏の、このテーマに関する記事をおすすめします。非常に詳しく解説されており、随所に役立つコードスニペットも掲載されています。

より効率的なトランザクションスケジューラー

現在の実装

トランザクション処理パイプラインでは、トランザクションのパケットがまずパケットイングレスを介してシステムに入ります。その後、これらのパケットはSigVerifyステージで署名検証を受けます。このステップでは、各トランザクションが有効であり、送信者によって承認されていることを確認します。

署名検証後、トランザクションはBanking Stageに送られます。Banking Stageには6つのスレッドがあります。そのうち2つは、Transaction Processing Unit(TPU)またはGossipからの投票トランザクション処理専用で、残りの4つは非投票トランザクションを処理します。各スレッドは互いに独立しており、共有チャネルからパケットを受信します。つまり、SigVerifyはパケットをバッチ単位で送信し、各スレッドはその共有チャネルからトランザクションを取得してローカルバッファに保存します。 

ローカルバッファはトランザクションを受信し、その優先順位を判定して、順番に並べます。このキューは動的であり、トランザクションの状態やネットワーク需要のリアルタイムな変化を反映するため、継続的に更新されます。トランザクションがキューに追加されるたびに順序が再評価され、優先順位が最も高いトランザクションから処理できる状態に保たれます。

このプロセスは継続的に行われ、トランザクションパケットがどう扱われるかは、リーダースケジュールにおけるバリデーターの位置によって決まります。バリデーターが近い将来にリーダーとして予定されていない場合、パケットを次のリーダーへ転送してから破棄します。バリデーターが予定されているリーダースロットに近づくと(約20スロット前)、パケットの転送は続けますが、破棄しなくなります。これは、他のリーダーがパケットを処理しなかった場合に、自身のブロックのいずれかにそのパケットを含められるようにするためです。バリデーターがリーダーになる2スロット前になると、パケットを保持し始めます。つまり、パケットを受け入れて何もせず、バリデーターがリーダーになった時点で処理できるようにします。

ブロック生成中、各スレッドはローカルキューの上位128件のトランザクションを取得し、ロックの確保を試みた後、トランザクションのチェック、読み込み、実行、記録、コミットを行います。ロックの確保に失敗した場合、トランザクションは後で再試行されます。各ステップを詳しく見ていきます。

  • ロック:このステップでは、スレッドがどのトランザクションのロックを確保できるかを確認します。各トランザクションは一定数のアカウントを読み書きするため、バリデーターは競合がないことを確認する必要があります
  • チェック:このステップでは、トランザクションが古すぎないか、すでに処理済みでないかを確認します。バンクには、直近150〜300スロットのトランザクションを追跡するステータスキャッシュがあります
  • 読み込み:このステップでは、特定のトランザクションの実行に必要なアカウントを読み込みます。また、手数料支払者が実際に手数料を支払えるか、呼び出されたプログラムが有効かどうかも確認します。基本的には、アカウントを読み込み、初期設定を行うステップです
  • 実行:このステップでは、各トランザクションを実行します
  • 記録:実行されたトランザクションの結果は、ハッシュ化のためProof of History Serviceに送信されます。ここでトランザクション署名が送信されます
  • コミット:記録ステップが成功すると、トランザクションがコミットされます。このステップでは、変更内容がアカウントシステムにも反映されるため、現在または後続のスロットにある将来のトランザクションは、各アカウントの最新状態を参照できます‍
  • ロック解除:最初のステップで各アカウントに設定されたロックを解除します

Banking Stageでは、マルチイテレーター方式を使用してトランザクションのバッチを作成します。マルチイテレーターとは、データセットを複数のシーケンスで同時に走査できるようにするプログラミングパターンです。1冊の本を複数の読者が異なる章から読み始め、内容の理解が互いに干渉する可能性がある場合には、同じページを同時に読まないよう連携する様子を想像してください。Banking Stageでは、この「読者」がイテレーターで、「本」が処理待ちのトランザクション群です。マルチイテレーターの目的は、トランザクションを効率的に選別し、ロック競合なしで処理できるバッチにまとめることです。

最初に、トランザクションは優先順位に基づいてベクターへ直列化されます。これにより、マルチイテレーターは構造化されたシーケンスを使用して、トランザクションを競合しないバッチに分割できます。マルチイテレーターは直列化されたベクターの先頭から開始し、トランザクションが互いに競合しない位置にイテレーターを配置します。これにより、読み取りと書き込み、または書き込み同士の競合がない128件のトランザクションからなるバッチを作成します。トランザクションが現在作成中のバッチと競合する場合、そのトランザクションはスキップされ、マークされないまま残ります。そのため、競合が解消された後続のバッチに含めることができます。この反復プロセスは、トランザクションの処理が進むにつれて動的に調整されます。 

バッチが正常に作成されると、トランザクションが実行され、成功した場合はProof of History Serviceに記録され、ネットワークへブロードキャストされます。

現在の実装の問題点

現在の実装には、パフォーマンスへ悪影響を及ぼし、トランザクション処理のボトルネックや優先順位付けの不整合につながり得る領域がいくつかあります。これらの課題は、主にBanking Stageのアーキテクチャと、システム内でのトランザクション処理の性質に起因します。

根本的な問題は、非投票トランザクションを処理する4つの独立したスレッドが、それぞれのスレッド内でトランザクションの優先順位を独自に認識していることです。この差異により、トランザクションの順序に揺らぎや不整合が生じる可能性があります。優先順位の高いトランザクションがすべて競合すると、この差異はさらに顕著になります。パケットは基本的に、SigVerifyからの共有チャネルから各スレッドによってランダムに取得されるため、それぞれのスレッドには全トランザクションのうちランダムな組み合わせが割り当てられます。人気NFTのミントのように競争が激しいイベントでは、多数の高優先度トランザクションが複数のBanking Stageスレッドに入る可能性があります。これは、スレッド間のロック競合を引き起こす可能性があるため問題です。異なる優先順位セットを扱うスレッド同士が、高優先度トランザクションを処理しようと競合し、ロックの確保に失敗することで、意図せず処理時間を浪費する可能性があります。

Banking Stageを、各スレッドが弦楽器、金管楽器、木管楽器、打楽器といった異なるセクションを担当するオーケストラだと考えてください。理想的には、指揮者が各セクションを調整し、調和の取れた演奏を実現します。しかし、現在のシステムは、指揮者なしで複雑な曲を演奏しようとするオーケストラに似ています。各セクションが独自の旋律を演奏し、たびたび衝突します。高優先度トランザクションは、すべてのセクションが同時に演奏しようとするソロパートのようなもので、混乱を招きます。この連携不足は、オーケストラを率いる指揮者のように、Solanaのトランザクション処理の効率性と調和を確保する中央集約型の「指揮者」が必要であることを示しています。

新しいトランザクションスケジューラー

1.18アップデートでは中央スケジューリングスレッドが導入され、4つの独立したバンキングスレッドがそれぞれトランザクションの優先順位付けと処理を管理していた従来のモデルを置き換えます。この新しい構造では、中央スケジューラーのみがSigVerifyステージからトランザクションを受信します。そして、優先度キューを構築し、依存関係グラフを使用してトランザクションの優先順位付けと処理を管理します。

この依存関係グラフはprio-graphと呼ばれます。これは有向非巡回グラフであり、新しいトランザクションが追加されるたびに遅延評価されます。トランザクションは実行チェーンを作成するためにグラフへ挿入され、その後、時間と優先順位に基づく順序で取り出されます。競合するトランザクションを扱う場合、先に挿入されたものが必ず高い優先順位を持ちます。上の例には、トランザクションAからHまでがあります。トランザクションAとEは、それぞれのチェーン内で最も優先順位が高く、互いに競合しない点に注目してください。スケジューラーは左から右へ移動し、トランザクションをバッチ単位で処理します。

最初のバッチでトランザクションAとE、次にBとF、その次にC、D、G、最後のバッチでHが処理されます。図からわかるように、最も優先順位の高いトランザクションはグラフの上部、つまり最も左側にあります。スケジューラーは優先順位の高い順にトランザクションを調べ、競合を特定します。トランザクションがより優先順位の高いトランザクションと競合する場合、その依存関係を表すエッジがグラフに作成されます(たとえば、CとDはBと競合します)。

新しいスケジューラーモデルは、マルチイテレーター方式に固有のいくつかの主要な問題に対処します。

  • 優先順位処理の一貫性:新しいシステムでは、トランザクションの受け入れとスケジューリングを中央集約化することで、すべてのトランザクションが一貫した優先順位で処理されます。これにより、複数のスレッドがトランザクションの優先順位を異なる形で認識することで生じていた揺らぎが解消されます
  • 処理遅延の削減:prio-graphにより、実行用に準備されたバッチがロック競合なしで成功する可能性が非常に高くなり、処理時間とロック競合による遅延が削減されます。「成功する可能性が非常に高い」という表現に注意してください。投票スレッドと競合する可能性があるため、prio-graphがロックに必ず成功するバッチを作成するというのは厳密には正しくありません。ただし、これは非常にまれなエッジケースです
  • 拡張性と柔軟性:この新しいスケジューラー設計では、ロック競合の増加を懸念することなく、スレッド数を増やせます。これは、ロックを中央集約的に把握し、ワーカー間でトランザクションをより制御された形で分配できるためです 

1.18で導入される中央スケジューラーは、トランザクション処理を大幅に改善し、従来のシステムに伴う複雑さとオーバーヘッドを軽減すると期待されています。これにより、トランザクション処理時間の短縮、スループットの向上、ネットワークの安定性向上が見込まれます。1.18のリリースが遅れたため、スケジューラーは当初からさらに改善されています。たとえば、効率を高めるため、トランザクションのプリコンパイル検証がワーカースレッドに移されました。また、CU制限も旧スケジューラーより妥当になり、推定値と実測値の比率が大幅に低下しています。新しいスケジューラーでは、CUを使用してスケジュール済みの作業キューを制限できるため、アカウント競合によって過剰な作業がキューに追加されるのを防げます。

中央スケジューラーはデフォルトで有効になっておらず、バリデーターの起動時に新しい**--block-production-method central-scheduler**フラグを使用して有効にする必要があります。現在はオプトインのみですが、今後のリリースではデフォルトのスケジューラーになります。また、--block-production-method thread-local-multi-iteratorフラグを使用すると、旧スケジューラーを有効にできます(現時点ではデフォルトで有効ですが、今後のリリースでは使用しないでください。中央スケジューラーのほうがはるかに効率的で、旧スケジューラーに存在する問題を解決します)。

より効果的な優先順位計算 

1.18では、トランザクションの優先順位を決定する方法も改良され、リソース使用量とコスト回収の面で、より公平かつ効率的なプロセスになりました。以前のトランザクションの優先順位付けは、主にコンピュートバジェットの優先順位に基づいており、コンピュートユニットの価格が最適にならない場合がありました。これは、優先順位付けで徴収される基本手数料が十分に考慮されておらず、リソースが過小評価され、ネットワークの運用効率に影響する可能性があったためです。

新しい方式では、**Priority = Fees / (Cost + 1)**という式を使用し、トランザクション手数料と関連コストを考慮するように優先順位計算を調整します。ここで、Feesは特定のトランザクションに関連するトランザクション手数料を表し、CostはSolanaのコストモデルによって算出されるコンピュートおよびリソース消費量を表します。分母に「1」を加えるのは、ゼロ除算を防ぐための安全策です。 

式をさらに分解し、FeesとCostをより明確にできます。

トランザクションのコストは、関連するすべてのコンピュートコストと運用コストを考慮して、包括的に計算されるようになりました。これにより、優先順位の計算にトランザクションの実際のリソース消費量が反映されます。つまり、開発者とユーザーは、要求するコンピュートユニットが少ないほど高い優先順位を得られます。また、優先手数料のない単純な送金にも、キュー内で一定の優先順位が与えられます。

プログラムデプロイの改善

1.18では、デプロイの信頼性と実行効率の両面で、プログラムのデプロイも大幅に改善されています。 

このアップデートでは、エポックの最終スロットにデプロイされたプログラムに、次のエポックで予定されているランタイム環境の変更が正しく適用されない問題を解決します。そのため、この移行期間中にデプロイされたプログラムは、誤って古いランタイム環境を使用していました。1.18ではデプロイプロセスが調整され、エポックの終わりにデプロイされたすべてのプログラムのランタイム環境が、次のエポックの環境と一致するようになります。

1.18では、CLIのプログラムデプロイコマンドに**--with-compute-unit-price**フラグを追加することで、デプロイトランザクションにコンピュートユニット価格または上限を設定できない問題にも対処しています。このフラグは、solana program deployコマンドおよびsolana program write-bufferコマンドで使用できます。コンピュートユニット上限は、各種デプロイトランザクションをシミュレーションし、消費されたコンピュートユニット数に設定することで決まります。  

もう1つの重要な改善は、大規模なプログラムデプロイにおけるブロックハッシュの処理方法です。1.18より前は、sign_all_messages_and_sendを使用して送信されたトランザクションは100 TPSに制限されていました。大規模なプログラムでは、デプロイトランザクションの数が数千件に達します。その結果、多くのトランザクションが一度に10秒以上遅延し、期限切れのブロックハッシュを使用するリスクがありました。1.18では、スロットリングによる遅延が終わるまで、最近のブロックハッシュを使用したデプロイトランザクションへの署名を遅らせます。ブロックハッシュは5秒ごとに更新されるようになったため、500件を超えるトランザクションを伴うデプロイでは、より新しいブロックハッシュを使用できるメリットがあります。

さらに、1.18では、ネットワークがプログラムのデプロイを処理し、トランザクションを検証する方法も改善されています。以前は、アカウントの状態を識別する際のエラーにより、一部のプログラムが誤ってFailedVerificationとマークされていました。その結果、実際にはチェックに失敗していないプログラムが誤って分類される可能性がありました。現在は、アクティブであるべきでないプログラムがClosedとして正しく識別されます。この変更により、問題のあるプログラムだけが再チェック対象としてフラグ付けされ、不要な再検証を防げます。

プログラムの状態を更新するプロセスも改良されました。プログラムは、デプロイされた同じタイムスロット内で、Closed状態からアクティブ状態へ移行できるようになりました。これによりプログラムは、より迅速かつ確実に稼働を開始できます。これは需要が高い時間帯に特に重要です。ただし、この改善には引き続き、1スロットのアンデプロイ、再デプロイ、デプロイのクールダウンと、1スロットの可視性遅延が適用されます。そのため、これらの調整はネットワーク負荷をより効果的に管理し、特定の種類の輻輳を防ぐのに役立ちますが、dApp開発者のワークフローを大きく変えるものではありません。

「輻輳パッチ」— 輻輳への対応を改善

「輻輳パッチ」と称されたTestnetバージョン1.18.11では、Solanaで最近発生した輻輳に対処するための変更が提案されました。このリリースは1.18固有のものではなく、1.17.31にもバックポートされています。それでも、非常に重要なため取り上げます。

大きな変更点は、QUICがStake-Weighted Quality of Service(SWQoS)において、ステーク量が極端に少ないピアを、ステークされていないピアとして扱うようになったことです。これは、ステーク量が非常に少ないステーキング済みノードがシステムを悪用し、不釣り合いな帯域幅を得られる問題に対処するためです。また、既存のメトリクスでは、ステーキング済みノードと未ステーキングノードから送信またはスロットリングされたパケットの比率を把握できませんでした。そのため、可視性を高める目的でこれらのメトリクスが追加されました。さらに、パケットごとのアロケーションを1回削減するため、vecの使用箇所をsmallvecに置き換え、パケットチャンクの処理方法も最適化されました。ストリームはパケットサイズであり、数も少ないと予想されるため、これが可能です。 

以前のBanking Stageでは、すべてのパケットが次のノードに転送されていました。しかし、**1.18では、ステーキング済みノードからのパケットのみが転送される**ように変更されました。このアップデートにより、ステーク接続は優先順位の計算とトランザクションの転送においてより大きな比重を持つため、これまで以上に重要になります。

ドキュメントの改善

1.18アップデートでは、世界中のユーザーがより利用しやすくなるよう、Solana公式ドキュメントの翻訳サポートも大幅に改善されています。更新内容には、言語間でのドキュメント同期を効率化するCrowdinのCLIと設定のアップグレード、およびDocusaurusを介したローカルテストを改善する新しいserveコマンドの導入が含まれます。また、翻訳版ビルドで相対パスに関する問題が発生しないよう、PDFファイルをGitHubのblobに直接リンクすることで、静的コンテンツの処理方法も改善されています。

開発者向けには、必要な環境変数や一般的なビルドエラーなどのよくある問題への対処方法を説明する更新版READMEにより、翻訳に貢献するプロセスが明確になりました。さらに継続的インテグレーションのフローも改善され、翻訳は安定版チャネルのビルドにのみ含まれるようになりました。これにより、検証済みの安定したドキュメントだけがエンドユーザーに提供されます。これらの変更は、コントリビューションを簡素化し、公式ドキュメントの品質を高め、すべてのユーザーが信頼性の高い正確な情報にアクセスできるようにすることを目的としています。

まとめ

Anzaが主導する1.18アップデートでは、トランザクション処理、優先順位計算、プログラムのデプロイ、公式ドキュメント、ネットワーク全体のパフォーマンスが大幅に改善されます。中央スケジューラーの導入と、最近の輻輳に対処するためのさまざまな修正により、Solanaはピーク負荷により適切に対応し、効率的で信頼性の高いネットワーク動作を実現できるようになります。Solanaはスケーラブルなブロックチェーンを実現する最有力候補であり、このアップデートはその可能性を裏付けています。

ここまで読んでくださった皆さん、ありがとうございます!Solanaの最新情報を見逃さないよう、ぜひ下にメールアドレスを入力してください。さらに詳しく知りたいですか?Heliusブログの最新記事を読み、今日からSolanaの探求を続けましょう。

その他のリソース

Heliusを購読

Solana開発の最新情報や新しい記事の公開通知を受け取れます

拡大画像