🔨Solana 開発における基礎知識. 公式DocやCookbookその他Tipsの個人的まとめ.

🔧Solana Programs

Solanaにおける📝スマートコントラクト.

  • 汎用プログラムのC/Rustで記述できるところが魅力(cf. EVMは📝Solidityという特化言語).
  • Solanaが高速に処理を行うためProgram自体は参照するためのデータを保持できないという縛りがある.
  • 🔖Statelessが特徴, 状態は持たない, 📝第一級関数のようなもの.

2つの種類.

  • Native Program
  • Solana Program Library, 🔧SPL

Native Program


Accounts

Solanaにおける基本的なデータ構造. オンチェーン上に存在するデータを入れた箱. Programが処理をする際には各種参照するデータが必要なので, これらを渡す必要がある.

属性

  • data: データそのもの.
  • owner: アカウントの所有権をもつアドレス.
  • lamports
  • exectable: trueならばプログラムアカウント.
  • 全てのアカウントは一位の公開鍵(address)をもつ, IDのようなもの.

Account Models

Solanaには三種類のアカウントがあります.

  • データアカウント: データの保存を行います。
    • システムが所有するアカウント
    • PDAアカウント
  • プログラムアカウント: 実行可能プログラムの保存を行います。
  • ネイティブアカウント: System、Stake、VoteなどのSolanaのネイティブプログラムを意味します.

🔧rent(Solana)

データアカウントにデータを保存し続けるためにはSOLの支払いが必要となり, これはrent(家賃)と呼ばれるものにより賄われることになります. Solanaでは、アカウントはメモリを消費するため, レンタル料が発生する. この料金は, 不活動のアカウントがシステムから削除されるのを防ぐためのもの.

  • accountのrent_epoch属性で次の支払日がわかる.
  • 📊Step Financeにはaccount-toolsというものがあり残高がないアカウントをクローズする機能がある.
    • https://app.step.finance/en/account-tools
    • Every token account requires ‘rent’. In most cases when the token balance is zero you can safely close the account and reclaim the SOL. Step charges a 5% fee for this service, and the amount reclaimed is paid in SOL.

ref. rent(家賃) | Solana Cookbook

💭OrderBook CEXは少額ゴミ残高がWalletに残ってしまうがAMM DEXだとそれがない(23/12/31)

🔦アカウントはユーザ情報ではなくファイルのようなバイナリデータ

アカウントという言葉がとっつきにくい. なぜならばネット世界でのアカウントは, webサービスの利用者の意味合いが強く, どうしてもデータという概念と結びつきにくい.

先ほど、アカウントはファイルのようなものだと言いましたが、PC 上のファイルであれば、そのファイルを作成したプログラムによって、中身のデータの種類やフォーマットはまちまちです。

ワードプロセッサアプリのデータファイルと、メールプログラムのデータファイルでは、当然ファイルの内容や形式は全く異なります。

同じように、Solana のアカウントも、そのアカウントを作成したプログラムによって、アカウントに含まれるデータの種類やフォーマットはまったく異なるわけです。

Account State

Solana Transaction(Tx)

Solanaにおける📝トランザクション(Tx)の仕組み.

SolanaのtransactionはlegacyとVersinedTransaction(0と表記される)の2つの種類がある.

構成要素

  • list of instructions
  • list of accounts
  • recent blockhash
  • signature: TXを識別するためのUUID.

Instructions

Solanaの基本的な操作単位がInstruction.

複数のAccountsとInstruction Dataをもつ.

Solana Tx送信

トランザクションライフサイクル

Solana Tx送信の手順.

  1. instructionsを構築する.

  2. recent blockhashをfetchしてinstructionsと共にmessageを構築する.

  3. transaction simulationを実行する.

  4. 秘密鍵でmessageに署名をする.

  5. RPCノードにtransactionをsendする. RPCノードはBlock Producerにforwardする.

  6. block producersがtxをvalidateしてcommitする.

  7. txが複数のblock producersにvalidateされるとcomfirmとなる.

  8. ref. https://docs.solana.com/developing/transaction_confirmation#transaction-lifecycle-refresher

  9. Lifecycle of a Solana Transaction

    • この記事にも図解がある.

sendTransaction

RPC endpoint.

preflightCommitment

sendTransaction/simulateTransactionのoptions. defaultはfinalized.


skipPreflightをtrueにす場合でもこの値はgetLatestBlockhashで指定したoptionと一致させることが強く推奨されている.

simulationのときと送信時のcommitment levelが異なる場合, “blockhash not found”となる. ただこのエラーが帰ってきてもチェーンへのtx送信は実行されていることに注意.

If the block chosen for simulation is older than the block used for your transaction’s blockhash, the simulation will fail with the dreaded “blockhash not found” error.

🔌Preflight

トランザクションがブロックに取り込まれる前の検証や前処理のこと. トランザクションを実際にブロックチェーンにコミットすることなく, 仮想的にそのトランザクションを実行して結果を確認する機能. RPCノード上で実行される.

エラーチェックや手数料の検証を行う.

  • Verify that all signatures are valid
  • Check that the referenced blockhash is within the last 150 blocks
  • Simulate the transaction against the bank slot specified by the preflightCommitment

simulateTransaction

Preflightはchainにcommitする前の検証だが, API endpointとしても類似の機能が提供されている.

Preflight Check(skipPreflight)

Preflightの検証はsendTransactonのオプションで無効化できる.

  • trueでskip. トランザクション送信処理のオーバヘッドを削減できる.
  • defaultはfalse. 開発ではskipPreflight=false推奨.

🔧Legacy Transaction

従来のSolana Txの仕様.

SolanaのTransactionは1280 byte(これはIPv6 MTU sizeからの制限).

  • Message領域: 48 bytes
  • Compact array of Signatres: 1232 byte
    • signatureは64 byte.
    • 理論上のmax accountsは35 accoutsまで.
      • ひとつのaccountsは32byte.
      • 32 x 35 + (metadata) = 1232 byte

🔧VersionedTransaction

VersionedTransactionが必要なのは, とくにたくさんの処理をひとつのtxに詰め込もうとしたときに従来の仕様だと容量制限がある. それをAddress Lookup Tablesをつかうことで拡張できるという圧縮技術による改善.


ref. Composing with Versioned Transaction with Jupiter | Jupiter Station

MessageV0

VersinedTransactionのmessageはMessageV0という.

  • Compact array of instructions: change from legacy
  • Compact array of address table lookups: introduced in v0

instructionsはcompiledされているのでdecompileしてカスタムinstructionsを追加して再度compileするためにはALTsが必要.

Transactionのsize取得

JavaScript(web3.js)の場合は, serializeしてlengthでObjectのサイズ取得.

marginが少しある.

const size = serialized.length + 1 + (transaction.signatures.length * 64);

RangeError: encoding overruns Uint8Array

1232byte サイズオーバー. これはcompileToV0Message()のときに発生する例外.

solana_sdk::transaction::versioned::VersionedTransaction too large: 1668 bytes (max: encoded/raw 1644/1232)

VersionedTransactionの容量オーバーのときのエラーメッセージ. max: encoded/raw 1644/1232.

この1232byteというのは, Solana Txのmax である1280 bytesからメタ情報を差し引いたpacketに割り当てられた領域のサイズ.

ref. https://solanacookbook.com/ja/guides/versioned-transactions.html#legacy-transaction

📝Address Lookup Tables

Address Lookup Tables, lookup tables, ALTs. LUTs.

transactionsの中で効率的にアドレスを管理するためのsolanaの仕組み, アドレス圧縮技術, 参照テーブル.

  • ひとつのALTに256のaddresssをいれられる.

Why

具体的には, 一つのtxでdefaultで35のaddressを扱えるが, これを256に拡張. これは圧縮技術によって一つのアドレスを32byteから1byteにすることによって256まで拡張する.

versioned transactionsというformatで記述. 実用的にはinterfaceで読み書きする.

これはMessageV0をdecompileして再度compileするときにも必要な情報となる. TxのなかにはAddress Lookup TableのAccount Addressesしか入ってないので, Txのなかのmessageをdecompile/compileするときは, このLUT AddresssKeyからAccountInfoをチェーンから取得する必要がある.

interfaces

https://solana-labs.github.io/solana-web3.js/classes/AddressLookupTableProgram.html#extendLookupTable

Usage

  • ALTの作成:
    • web3.AddressLookupTableProgram.createLookupTableでinstructionを作成してtxで送信.
  • lookupTableAddressにaddressを追加.
    • web3.AddressLookupTableProgram.extendLookupTableでinstructionを作成してtxで送信.
    • addressの削除はないようだ.
  • LookupTableAddressからアドレス解決

with VersionedTransaction(compileToV0Message)

  • lookupTableAddress(これはたんなるaddressのpubkey)からAddressLookupTableAccountを取得.

  • AddressLookupTableAccountのリストを引数にしてcompileToV0Messageでtx作成.

Altsはtxにいくつまで追加できる?

Solanaのドキュメントには明示されていない(ChatGPTは4つと平気で嘘ついた). おそらくtxサイズの限界まで. Solscanで表示されないのは, ALTに含まれるアドレスがまったく利用されない場合はそもそも表示もされないと推測.

Altsの分析にはSolscanよりもsolana explore(inspect)のほうがよい.

あるuserの作成したすべてのLTAを取得

solana program - How can i fetch all the address lookup table accounts created by an account(payer)? - Solana Stack Exchange

connection.getProgramAccounts(AddressLookupTableProgram.programId, {
  filters: [
    {
      memcmp: {
        offset: 22,
        bytes: payer.publicKey,
      },
    },
  ],
});

中身はdecodeして解析が必要.

Viewer

🔍Solana ExploreのAddress欄のTable Entriesが見やすい.

Program

Refs

📝PDAs

プログラム派生アドレス/Program Derived Address.

  • Program IDとseed(乱数)から生成されるアドレス.
    • findProgramAddressSync
  • PDAは公開鍵のように見える32byteの文字列, しかし秘密鍵を持たない.

🔌Solana CPI

Cross Program Invocations, CPI.

Programの中で他のProgramを呼び出す. これにより、複数のプログラムが連携して動作する複雑な操作を実現できる.


  • これはSolana独自用語. 一般的にはなんという?
  • 公開されているAPIによってサービスが連携するようなもの. オンチェーンにあるProgramは基本全公開でありだれでも呼び出せる, それらのProgramを機能として呼び出すことで, 自分のやりたい機能を実現する.
  • SolscanではInner Instructionsとして表示される.

🔧SPL Token Program

🔧SPLフレームワークのなかのToken Program. Solscanで頻出.

🪙SPL Token

SPL Token, またはSPL Token Account.

🔧SPLフレームワークで作成されたトークン.

👛Wallet Account

  • owner: system program

👛Solana Walletで管理する.

🪙Associated Token Accounts(ATAs)

Associated Token Accounts(ATAs).


🔧solana/spl-token

ATAをcloseするには?

不要なATAをcloseすることで, rentをredeemすることができる. いいかかれば, Solanaチェーンに預けてるSOLを回収することができる.

ATAがtokenProgramかtokenProgram22かを判定するには?

getAccountInfoしたあとに owner属性をみる.

LP TokenはATA

LP TokenはたんなるATAの場合があるので注意.

💭Solanaで8万円を間違えてバーニング(burn)した(24/11/28)

🪙Mint Token

Mint Token Accounts.

Solanaエコシステムにおけるトークンの発行元. さらにそのpubkeyはmint addrsssと呼ばれる.

https://solscan.io/tokens

cf. 🪙SPL Tokenは個人のwalletのtoken.


SPLではデータは整数で保存される. 実際の値は📝decimalsという小数点以下の桁数で割る.

たとえばUSDCのdecimalsは6であり, 実際の整数値から10^6で割った値となる. このdecialsはToken Accounts生成時に定義されて, Token Accountごとに異なる.


<2025-03-04 Tue 09:35> mintはSolana特有の用語で、ERC-20ではToken Contract Address.

Token Metadata Account

NFTで管理されるMint Accountのメタ情報. 現在のSolana EcosystemではMetaplexがそれを担う.

🔧Mpl Token Metadata

📝Solana IDL

🔧SPL Token Programのインターフェイス言語.

Solana開発では大抵の場合は🔧Anchor(Solana)のフレームワークをつかってクライアントコードを生成する.

  • json形式でファイル保存される.
  • Public IDLは Solana のBlock ExploreからDownloadできる.

Transacton Fee

Solana Txを発行するときの手数料.

Transaction Fee = Compute Units used by the transaction × Compute Unit Price

📝lamports(Solana)

手数料の最小単位. A fractional native token with the value of 0.000000001 sol.

  • 1 SOL = 1,000,000,000 lamports(0が9こ, billion)
  • 1 Lamports = 0.000000001 SOL
  • 1 MicroLamports = 0.000001 Lamports

📝Prioritization fee(Solana)

Priority fee, Prioritization fee. 優先順位ための追加で支払うfee.


Base Fees

tx送信のための最小のfee.

  • 5000 lamports = 0.000005 SOL.

getRecentPriorizationFees

getRecentPriorizationFeesという関数で最近の平均feeを確認できる.

Priolity fee最適化

📝Solana Compute Budget

Compute Budget.

  • Validatorに支払う上乗せFeeのようなもの.
  • Txの計算リソース(CPU使用量)
  • 上限は200000 Compute Unit.
  • SolanaのFeeは0.000005SOLで固定.
#1 - Compute Budget: Set Compute Unit Limit
#2 - Compute Budget: Set Compute Unit Price

Compute BudgetのInstructionsがTxに2つ以上含まれるとエラーになるので注意.


Compute Fees

Compute Units(CU)

トランザクションが必要とするコンピュートの量。Solanaのトランザクションは、それがネットワークにかかるコストに基づいてこのユニットで計量されます.

コード上の定義.

https://github.com/solana-labs/solana/blob/090e11210aa7222d8295610a6ccac4acda711bb9/program-runtime/src/compute_budget.rs#L26-L87

setComputeUnitLimit

  • 上限値(200k/200000CU)の変更.
  • 適切にsetComputeUnitLimitを設定しないとtxはdropするリスクがある. 200k CUを超える場合.
  • priolity feeを設定しないならばsetComputeUnitLimitは不要(default 200k CUとなる).
  • Jupiterだと1400000を設定してるようだ.

適切なCompute Budget を設定するには最低値を設定して実験してみる. エラーすると Computational budget exceeded のようになる.

  • Program failed to complete
  • Computational budget exceeded

最適化しないと不要なfeeを支払うことになる.

https://solanacookbook.com/references/basic-transactions.html#how-to-change-compute-budget-fee-priority-for-a-transaction

Compute Budget最適化

ベストプラクティスはsimulateTransactionで事前に最適なCUを見積もって設定すること.

How to Request Optimal Compute Budget | Solana

🔖Solana Validators

Solanaチェーンにおける📝バリデータ(Validators).

💡Compute Budget, いわゆるFeeはValidatorの収入源.


leader

The role of a validator when it is appending entries to the ledger.

ledger

list of entries containing transactions signed by clients. Conceptually, this can be traced back to the genesis block, but an actual validator’s ledger may have only newer blocks to reduce storage, as older ones are not needed for validation of future blocks by design.

Block

blockは複数のトランザクションをもつ.

Slot

Solanaにおける時間の単位. logical clock.

blockhash

  • blockの識別子, timestampのようなもの.
  • 📝PoHにおけるhash for slot(Solana独自概念).

Transaction Confirmation | Solana Docs

  • blockhash expirations

    blockhashには期限がある. 151slotで期限切れ.

    だいたい1slotが600ms~800msで見積もると, 60sec to 90 secで期限切れ.

Transaction Confirmation

トランザクションのValidatorsによる承認プロセス.


Transaction Process Status

3つのstateを指定してtxをqueryできる. Solanaチェーンの分散性のため, ある時点のqueryが最終的な結果とかは限らない(rollbackされるかも).

  • processed:
    • トランザクションがバリデータによって処理されたことを示しますが、まだ完全に確定されていないことを意味します。トランザクションが処理された後、すぐにこのステータスが与えられます。
    • Query the most recent block which has reached 1 confirmation by the connected node
    • 大体5%はdropするらしい.
  • confirmed: トランザクションがネットワークの大部分によって確認されたことを示します。これは、トランザクションが正しく、変更の可能性が非常に低いことを示していますが、最終的な確定ではありません。
    • Query the most recent block which has reached 1 confirmation by the cluster
  • finalized: トランザクションが完全に確定され、変更されることはありません。Solanaの安全性モデルにおいて、最終化されたトランザクションは変更されることがないと考えられています。
    • Query the most recent block which has been finalized by the cluster

ref. https://docs.solana.com/api/http#configuring-state-commitment

getLatestBlockhash

Blockhashを取得. paramsでstatusも指定できる. defaultはfinalized.

📝TPU(Solana)

Transaction Processing Unit.

TPU | Solana Docs

Refs

🔗References

🔨Solana 開発