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

Solanaのトランザクションと命令
Solanaでは、ユーザーはトランザクションを発行することでプログラムを実行します。Solanaのユニークな点は、これらのトランザクションを並列に実行できることであり、これがその超高速トランザクション速度の主な理由です。では、Solanaにおけるトランザクションの設計をより詳しく見ていきましょう。
Solanaのトランザクションは署名とメッセージで構成されています。トランザクションには複数の署名を含めることができます。トランザクションのメッセージは、以下に示すように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スキャンでSolanaトランザクションを確認する
別のSolanaエクスプローラーを使用して、先ほどのプログラムアカウントを作成したトランザクションを確認します。Overviewセクションでは、Solanaのトランザクション署名、最近のブロックハッシュ、その他の情報を確認できます。

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

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

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



