はじめに
2024年、Solanaは、年初の10億米ドルから約50億米ドルへと預け入れ総額(TVL)が急増し、4番目に大きいパブリックブロックチェーンとして劇的に台頭しました。
イーサリアムと比較して、Solanaはより高速な速度と低コストでユーザーに優れた体験を提供します。Proof of Historyベースのコンセンサスアルゴリズムと非同期トランザクション処理モデルは、開発者に高いトランザクションスループットと低レイテンシーをもたらし、あらゆる種類の分散型アプリケーションにとって好ましいプラットフォームとなっています。
BlockSecは、Solanaの基本概念、Solanaトランザクション分析の実践ガイド、Solanaスマートコントラクト作成チュートリアルを網羅した「Solana Simplified」シリーズを特別に企画しました。
このシリーズの最初の記事として、本稿ではSolanaネットワーク内の主要な概念、その動作メカニズム、アカウントモデル、トランザクションについて掘り下げ、Solanaで正確かつ効率的なスマートコントラクトを作成するための基礎を築きます。
eBPF:Solanaトランザクション実行の要
スマートコントラクトを作成・実行するためには、ブロックチェーンには通常、プログラミング言語とチューリング完全な計算環境が必要です。
イーサリアムのスマートコントラクトは、通常、Solidityと呼ばれる高水準言語で記述されます。コンパイラはこれをバイトコードに変換し、イーサリアム仮想マシン(EVM)で実行されます。Solanaは、全く新しい仮想環境と言語を開発する代わりに、既存の高度な技術を最大限に活用することを選択しました。Linuxカーネルの機能を拡張するために当初設計されたeBPF(extended Berkeley Packet Filter)仮想マシンを、Solanaは基盤となる実行環境として採用しました。
では、eBPFはEVMに対してどのような利点があるのでしょうか?
解釈実行に限定されるEVMとは異なり、eBPFはJIT(Just-In-Time)コンパイルをサポートしており、バイトコードをプロセッサが直接実行できるマシン命令に変換できます。このような機能は、プログラムの効率を大幅に向上させます。
さらに、eBPFは効率的な命令セットと成熟したインフラストラクチャを備えています。開発者はRust言語を使用してスマートコントラクトを作成できます。LLVMコンパイラフレームワークのeBPFバックエンドを活用することで、Rustプログラムは直接eBPFバイトコードにコンパイルできます。
Solanaのアカウントモデル
Solanaアカウント構造
Solanaでは、データはアカウントの形式で保存されます。以下に示すように、Solana内のすべてのデータは、巨大なキー・バリューデータベースとして概念化できます。このデータベースのキーはアカウントアドレスです。「ウォレット」アカウント(つまり、Solanaユーザーが公開鍵・秘密鍵ペアを介して直接制御するアカウント)の場合、これらのアドレスはEd25519署名システムを使用して生成された公開鍵です。データベースの値は、残高やその他の関連情報など、各アカウントの特定の詳細で構成されます。
Solanaは、アカウントを記述するために、AccountInfoとして知られる以下の構造を使用します。
各アカウントのAccountInfoには4つのフィールドが含まれます。それぞれの説明は以下の通りです。
-
Dataフィールド:このフィールドはアカウントに関連するデータを格納します。アカウントがプログラム(つまり、スマートコントラクト)の場合、eBPFバイトコードが格納されます。それ以外の場合、データの形式は一般的にアカウント作成者によって定義されます。 -
Executableフィールド:このフィールドは、アカウントがプログラムであるかどうかを示すために使用されます。イーサリアムとは異なり、Solanaのプログラムは更新可能であることに注意することが重要です。 -
Lamportsフィールド:このフィールドは、アカウントのSolanaトークンの残高を記録します。Lamportsは、SOLトークンの最小単位です(1 SOL = 10億 Lamports)。 -
Ownerフィールド:このフィールドはアカウントの所有者を示します。Solanaでは、すべてのアカウントに「オーナー」があります。例えば、すべての「ウォレット」アカウントのオーナーは、アカウント作成などの機能を担当するSolanaネットワーク上の特別なアカウントであるSystem Programです。アカウントのオーナーのみがアカウントデータを変更したり、残高からLamportsを差し引いたりすることができます(ただし、誰でも送金によってLamportsを増やすことができます)。
事前定義されたSolanaアカウント
Solanaには、Native Programsとして知られる事前定義された実行可能プログラムのセットがあり、固定アドレスにデプロイされています。Solanaネットワークがアップグレードされるにつれて、これらの事前定義されたプログラムも更新できます。これらは、Solanaネットワーク内で特定の機能を提供するAPIおよびライブラリ関数として機能します。
Native Programsの中で、開発者がよくやり取りするのはSystem Programです。System Programは、独立したタスクを実行する一連の命令を開発者に提供します。例えば、開発者はCreateAccount命令を使用して新しいアカウントを作成したり、Transfer命令を使用して他のアカウントにLamportsを転送したりできます。
もう一つの一般的なNative ProgramsはBPF Loaderプログラムです。これは、他のすべてのプログラムアカウントのオーナーであり、カスタムプログラムのデプロイ、更新、実行を担当します。プログラムアカウントを更新する必要がある「ウォレット」アカウントは、プログラムのオーナーのみがデータを直接変更する権限を持っているため、実際にはBPF Loaderプログラムに委任して行われます。
Native Programsに加えて、SolanaはSysvarsとして知られるアカウントのセットも提供しています。これらのアカウントは、Solanaネットワークの現在の状態、現在のクロックや最新のブロックハッシュなどに関連する情報とグローバル変数をSolana上のプログラムに提供します。
アカウントレント
Solanaブロックチェーンでは、各アカウントはレントとして知られる最低限の残高を維持する必要があります。実際のレントとは異なり、Solanaのレントは回収可能です。アカウントのデータがチェーン上で利用可能であることを保証するためには、アカウントは適切な量のLamportsを保持する必要があります。レントの金額は、アカウントが占めるデータサイズに関連しています。
アカウントの残高をレント額を下回るまで減らそうとするトランザクションは、残高を正確にゼロまで減らさない限り失敗します。残高をゼロにすることは、アカウントのレントが回収されたことを意味し、トランザクションの終了時にSolanaはガベージコレクションプロセスで対応するアカウントのデータをクリアします。
🧐 Solana ScansでのSolanaアカウントの表示
上記概念をよりよく理解するために、Solanaの"Hello World"プロジェクトを使用してプログラムアカウントをデプロイし、SolanaのブロックチェーンエクスプローラーであるSolscanで表示しました。

上記の画像に示すように、まずアカウントが「Program」とラベル付けされていることがわかります。このアカウントのレントとして送信者の残高から一部のLamportsが差し引かれたため、SOL Balanceフィールドは空ではありません。さらに、作成したアカウントはプログラムであるため、Executableフィールドは「Yes」に設定されています。
Executable DataフィールドにeBPFプログラムではなくアドレスが格納されていることに困惑するかもしれません。前述のように、Solanaはプログラムの更新を可能にしており、これは実際には「プロキシ」パターンを通じて実装されます。プログラムアカウントへの直接変更は当初許可されていないため、SolanaはeBPFプログラムを格納するための個別のデータアカウントを作成し、プログラムアカウントのDataフィールドにはこのデータアカウントのアドレスのみが格納されます。
プログラムの更新が必要な場合は、データアカウントのDataフィールドのみを変更する必要があります。Solscanを使用してデータアカウントを表示すると、「Program Executable Data Account」とマークされており、そのDataフィールドに実際のプログラムが格納されていることがわかります。

「More Info」セクションのOwnerフィールドはBPF Loaderであり、前述の内容と一致しています。
「Overview」の最後のフィールドに、AccountInfoには存在しないUpgrade Authorityがあることに気づく人もいるかもしれません。これは何を意味するのでしょうか?
前述のように、「ウォレット」アカウントはプログラムの更新をBPF Loaderに委任します。更新する前に、BPF Loaderは委任者がプログラムを最初にデプロイしたアカウントであるかどうかを確認します。プログラムアカウントのOwnerはすでにBPF Loaderに設定されているため、この情報を格納するスペースがありません。そのため、SolanaはこれをデータアカウントのDataフィールドに格納します。これが「Overview」にUpgrade Authorityフィールドがある理由であり、実際にはプログラムをデプロイしたウォレットアドレスです。
以下の画像は、プログラムアカウントとデータアカウントの関係を示しています。データアカウントのDataフィールドは、ウォレットアドレスとeBPFコードの両方で構成されていることに注意してください。

Solanaのトランザクションと命令
Solanaでは、ユーザーはトランザクションを発行することでプログラムを実行します。Solanaのユニークな点は、これらのトランザクションを並列実行できることであり、その驚異的なトランザクション速度の主要な理由となっています。それでは、Solanaのトランザクションがどのように設計されているかを詳しく見ていきましょう。
Solanaトランザクションは、署名とメッセージで構成されます。1つのトランザクションには複数の署名を含めることができます。トランザクションのメッセージは、以下の図に示すように4つの部分で構成されます。

HeaderとCompact Array of Account Addressesは、トランザクションに関与するすべての Вアカウントと、トランザクション中のそれらの特性(アカウントが署名者であるかどうか、実行中に書き込み可能であるかどうか)を指定します。この情報により、Solanaは署名 Вアカウントから提供された署名を検証し、これらのトランザクションが同じВステートに書き込む Вアカウントを一切含んでいない限り、トランザクションを並列処理できます。
Recent Blockhashは、トランザクションのタイムスタンプとして機能します。トランザクションのブロックハッシュが最新のブロックハッシュよりも150ブロック古い場合、それは期限切れと見なされ、実行されません。
Compact Array of Instructionsはトランザクションの最も重要な部分であり、1つ以上の В命令を含みます。 В命令は、プログラム Вアカウントによって提供されるルーチンの В実行をトリガーします。各 В命令は、以下の図に示すように3つのフィールドで構成されます。

最初のフィールド、Program ID Indexは、 В命令の受信者、つまり В命令を処理する必要があるオンチェーンプログラムを指定します。32バイトのアドレスを格納するのではなく、このアドレスはトランザクションメッセージのCompact Array of Account Addresses内に配置され、フィールドは配列内のアドレスを指すu8インデックスのみを格納します。
最初のフィールドと同様に、2番目のフィールドはCompact Array of Account Address Indexesとして知られる Вアカウントアドレスインデックスを格納します。この配列は、この В命令に関与する Вアカウントをすべて指定します。
最後のフィールドは、プログラムが В命令を処理するために必要な追加データ(関数引数など)を含むバイト配列です。
Solanaは、トランザクション内のすべての В命令を順番に処理し、トランザクションの Вアトミックな В実行を保証することに注意することが重要です。つまり、 Вすべての В命令が正常に処理されて完全に完了するか、 Вまったく В失敗するかのどちらかです。 В一部の В命令が処理され、 В他の В命令が処理されないという状況はありません。
🧐 Solana ScansでのSolanaトランザクションの表示
別のSolanaエクスプローラーを使用して、以前にプログラムアカウントを作成したトランザクションを表示しました。Overviewセクションでは、Solanaトランザクション署名、最近のブロックハッシュ、その他の情報を見ることができます。

Account Inputセクションには、現在のトランザクションに関与する Вアカウントがすべてリストされ、トランザクション中の Вそれらの В特性とともに示されます。送信者とプログラム Вアカウントアドレスに加えて、2つのNative ProgramsとSysvar Вアカウントも含まれていることがわかります。

これは単純なプログラム作成トランザクションであるため、2つの В命令しか含まれていません。最初の В命令の受信者はSystem Programであり、プログラム Вアカウントの作成を担当します。2番目の В命令の受信者はBPF Loaderであり、デプロイされたeBPFコードを格納するデータ Вアカウントを作成し、そのアドレスをプログラム ВアカウントのDataフィールドに書き込みます。

結論
SolanaのスマートコントラクトはRustで開発され、eBPF仮想マシンで実行されます。Solanaはアカウントモデルに従っており、オンチェーン Вアカウントはデータが削除されないように十分なレントを維持する必要があります。トランザクションは1つ以上の В命令で構成され、必要な Вアカウントをすべて定義し、並列処理を可能にしてスループットを向上させ、応答レイテンシーを削減します。これらの В機能が Вすべて В合わさって、Solanaの急速な В発展に В貢献し、 В好まれる Вブロックチェーンの1つとなっています。



