本文へスキップ
BecomeCoder

Solanaコース · 第3章 Solanaのアカウントモデル · レッスン9

すべてはアカウント ― コードとデータの分離

ローカル実施

導入

Solana では、「プログラム」も「そのプログラムが扱うデータ」も、どちらも同じ入れ物 ―― アカウント に格納されています。この「すべてはアカウント」という発想が、Solana のアーキテクチャ全体の出発点です。

説明

Solana 上のあらゆる情報は アカウント という単位で保存されます。アカウントには一意のアドレス(公開鍵)があり、そこに次のような情報が紐づいています。

  • 残高(SOL、正確には lamport
  • 中身のデータ(バイト列)
  • そのデータを実行可能なコードとして扱うかどうかのフラグ(executable
  • そのアカウントを管理する owner(次のレッスンで扱います)

プログラム(スマートコントラクト)は、executable: true が立った特別なアカウントとして保存されます。ここには実行可能なバイトコードが入っていますが、そのプログラムが使うデータそのものは、プログラムのアカウントには入りません。データは、プログラムとは別の「データアカウント」に置かれ、プログラムはそれを読み書きしにいく、という関係になっています。

classDiagram
    class SolanaProgramAccount {
      +pubkey Address
      +executable true
      +data バイトコード(コンパイル済みプログラム)
    }
    class SolanaDataAccount {
      +pubkey Address
      +owner ProgramAddress
      +data 状態データ(バイト列)
      +lamports 残高
    }
    class EthereumContract {
      +address Address
      +code バイトコード(EVM)
      +storage 状態データ(内蔵)
      +balance ETH残高
    }
    SolanaProgramAccount ..> SolanaDataAccount : 命令(instruction)経由で読み書き

Ethereum のコントラクトと比べると、この違いがはっきりします。Ethereum では「コントラクトのアドレス」1つに、コード(code)とストレージstorage)が両方とも内蔵されています。一方 Solana では、プログラムのコードを持つアカウントと、状態を持つデータアカウントが完全に分離しています。

この分離には利点があります。同じ1つのプログラム(例えばトークンを扱う共通のプログラム)を、無数の異なるデータアカウント(それぞれのユーザーのトークン残高など)に対して使い回せるのです。プログラムのコードを何度も複製する必要がなく、「ロジックは1つ、データはユーザーの数だけ」という構成が自然に作れます。

// Solanaプログラム側のイメージ(Rust)
// プログラム自体はロジックのみを持ち、状態は引数で渡される「データアカウント」に読み書きする
pub struct CounterAccount {
    pub count: u64, // データアカウントの中身の例
}

pub fn increment(account_data: &mut CounterAccount) {
    account_data.count += 1;
}

演習

同じ「カウンターを増やすプログラム」を、100人のユーザーがそれぞれ自分のカウンターとして使いたいとします。Solana のアカウントモデルでは、プログラムのアカウントとデータアカウントはそれぞれいくつ必要になるでしょうか。

ヒント1を見る

プログラム(ロジック)は全ユーザー共通で使い回せます。

ヒント2を見る

データ(カウンターの現在値)はユーザーごとに別々に持つ必要があります。