SVM開発
QoreChainにはSolana Virtual Machine (SVM)実行環境が組み込まれており、開発者は使い慣れたSolanaツールを使ってSBF/BPFプログラムをデプロイ・実行できます。SVMモジュールはポート8899でSolana互換のJSON-RPCインターフェースを公開しており、これはqorechaind startによって自動的に起動されます(以下のJSON-RPCサーバーを参照)。
以下のコマンドは、2026年6月7日から稼働しているチェインバージョンv3.1.97を実行中の**qorechain-vladi**メインネットを使用しています。テストネットの場合は--chain-id qorechain-dianaに置き換えてください。
チェインバージョンv3.1.89(8月22日)以降、インシデントを受けて、SVM実行レーンはトランザクション送信についてネットワーク全体で無効化されています——x/svm宛に送信されるトランザクション(プログラムデプロイ、命令実行、アカウント作成、送金)はすべてcode 11, "SVM module is disabled"を返します。これは自分自身のノードにもパブリックエンドポイントにも当てはまります。読み取り系のRPCメソッドは引き続き応答する場合がありますが、このレーンが再開されるまでは、実運用のSVM統合を構築したりリハーサルしたりしないでください。これはランタイムパラメータではなくコンパイル時の無効化であるため、ガバナンス投票によって再度有効化することはできません。外部監査によって問題なしと確認されるまで、無効のままとなる見込みです。
概要
x/svmモジュールは以下を提供します:
- ネイティブQORをファーストクラスのSVMアセットとして — アカウントの統合残高がlamports単位で参照できます
- SBF/BPFプログラムのデプロイと実行
- データアカウントの作成と管理
- Solana互換のJSON-RPCエンドポイント
- QoreChainとSolanaのアドレス形式間の双方向アドレスマッピング
- コンピュートバジェットの計測とレントベースのストレージ経済性
SVMインターフェース上のネイティブQOR
チェインバージョンv3.1.82以降、SVMインターフェースは独立したサンドボックス残高ではなく、ファーストクラスのネイティブQORインターフェースです。アカウントが持つ単一の統合残高——Cosmosインターフェースではuqorとして、EVMでは18桁小数のweiとして参照できるのと同じ資金——が、SVM側ではlamports(9桁小数)として表示されます:
1 uqor = 1,000 lamports · 1 QOR = 1,000,000,000 lamports
getBalance/getAccountInfoはアカウントのネイティブQOR残高(lamports単位)を返します。getSignaturesForAddressは、あるアドレスに関わるトランザクション履歴を返します——標準的なSolanaツールによる入金検知に利用できます。- System Programによる送金はネイティブQORを移動します — Solanaスタイルの送金命令は、Cosmosの
MsgSendやEVMの送金と同じ資金を移動させます。 - SVMアドレス形式 — アカウントのSVMアドレスは、20バイトのアカウントバイト列を32バイトになるよう右側にパディングし、base58エンコードしたものです。3つのアドレス形式(
qor1...、0x...、base58)はすべて同じアカウントを指します。
パブリックエンドポイント(https://svm.qore.host、https://svm-testnet.qore.host)は読み取り専用です——トランザクション送信はエッジ側で無効化されています。通常であれば、SVMトランザクションを送信するために自分自身のノード(ポート8899)を運用しますが、上記の注意事項のとおり、x/svmのトランザクションレーン自体が現在、自分自身のノードを含むネットワーク全体で無効化されています。
JSON-RPCサーバー
Solana互換のJSON-RPCサーバーは**qorechaind startによって起動**され、デフォルトで有効になっています。app.toml内の[svm-rpc]セクションで設定します:
[svm-rpc]
# Enable the Solana-compatible JSON-RPC server
enable = true
# Address the server listens on
address = "127.0.0.1:8899"
デフォルトはenable = true、address = "127.0.0.1:8899"なので、起動したばかりのノードはすでにポート8899でSolana JSON-RPCインターフェースを提供しています——@solana/web3.jsは追加設定なしでhttp://127.0.0.1:8899に接続できます。getVersionは1.18.0-qorechainを返し、getBalance / getAccountInfoはオンチェーンの実際のSVMアカウントを返します。
| プロパティ | 値 |
|---|---|
| デフォルトURL | http://127.0.0.1:8899 |
| 有効化 | デフォルトで有効 |
| 起動元 | qorechaind start |
| 互換性 | Solana JSON-RPC(サブセット) |
getVersion | 1.18.0-qorechain |
サポートされているメソッド
| メソッド | 説明 |
|---|---|
getAccountInfo | アカウントデータとlamport残高を取得 |
getBalance | アカウント残高をlamports単位(ネイティブQOR)で取得 |
getSignaturesForAddress | あるアドレスのトランザクション履歴 |
getSlot | 現在のスロット番号 |
getMinimumBalanceForRentExemption | 指定したデータサイズに対する最低残高 |
getVersion | SVMランタイムのバージョン情報 |
getHealth | SVMエンドポイントのヘルスチェック |
プログラムのデプロイと操作
最新のSBF実行。 SVM実行エンジンはsolana-sbpf 0.21.1へと刷新されており、現行のSolanaツールチェーン(platform-tools v1.53 / agave 4.x)でコンパイルされたばかりのSBFプログラムは、QoreChain上でデプロイと実行の両方が可能です——実行はデプロイのみでなく完全にサポートされています。cargo build-sbf --arch v0または--arch v3のいずれでビルドしたプログラムもサポートされます。
-
SBFプログラムをデプロイする — 現行のplatform-tools(v1.53 / agave 4.x)を使ってSolanaプログラムをSBF共有オブジェクトにコンパイルし、QoreChainにデプロイします:
# Build with the current Solana toolchain (--arch v0 or --arch v3)cargo build-sbf --arch v3# Deploy the compiled programqorechaind tx svm deploy-program ./my_program.so \--from mykey \--gas auto \--gas-adjustment 1.3 \-yトランザクションのレスポンスには、base58形式のプログラムIDが含まれます。
-
命令を実行する — 命令データを指定してオンチェーンのBPFプログラムを呼び出します:
# Execute instructionqorechaind tx svm execute <program-id-base58> <data-hex> \--from mykey \--gas auto \-yパラメータ 形式 説明 program-id-base58Base58文字列 デプロイ済みプログラムのアドレス data-hex16進エンコードされたバイト列 シリアライズされた命令データ -
データアカウントを作成する — プログラムは状態を保存するためにアカウントを必要とすることがよくあります。サイズとオーナーを指定してアカウントを作成します:
# Create data accountqorechaind tx svm create-account <owner-base58> <space> <lamports> \--from mykey \--gas auto \-yパラメータ 説明 owner-base58このアカウントを所有するプログラム(base58) spaceデータフィールドのサイズ(バイト単位) lamports初期残高(レント免除の最低額を満たす必要があります) 指定サイズに対するレント免除の最低残高を照会します:
# RPC: getMinimumBalanceForRentExemptioncurl -X POST http://localhost:8899 \-H "Content-Type: application/json" \-d '{"jsonrpc": "2.0","id": 1,"method": "getMinimumBalanceForRentExemption","params": [1024]}' -
@solana/web3.jsを使う — Solana JavaScript SDKは、QoreChainのSVMエンドポイントに対してそのまま動作します:
import { Connection, PublicKey } from "@solana/web3.js";const connection = new Connection("http://127.0.0.1:8899");// Check healthconst health = await connection.getHealth();console.log("SVM health:", health);// Get slotconst slot = await connection.getSlot();console.log("Current slot:", slot);// Get account infoconst pubkey = new PublicKey("YourBase58ProgramId...");const accountInfo = await connection.getAccountInfo(pubkey);console.log("Account data:", accountInfo);// Get balanceconst balance = await connection.getBalance(pubkey);console.log("Balance (lamports):", balance);
アドレスマッピング
QoreChainは、ネイティブBech32アドレス(qor1...)とSolanaスタイルのbase58アドレスとの間で双方向のアドレスマッピングを維持しています:
| 方向 | 例 |
|---|---|
| ネイティブ → SVM | qor1abc...xyzは決定論的なbase58アドレスにマッピングされます |
| SVM → ネイティブ | base58形式のプログラムアドレスは対応するqor1...に逆マッピングされます |
このマッピングは決定論的であり、x/svmモジュールによって管理されます。両方の表現は、同一の基盤となるアカウントを指します。
レントモデル
SVMモジュールは、状態の肥大化を防ぐためにレントベースのストレージモデルを採用しています:
| パラメータ | 値 |
|---|---|
| 1バイトあたり年間lamports | 3,480 |
| レント免除乗数 | 2.0 |
| 徴収頻度 | 各エポック |
- 残高が
2 * (data_size * 3480 / seconds_per_year)(lamports単位)を上回るアカウントはレント免除となり、決して課金されません。 - レント免除しきい値を下回るアカウントは、各エポックでレントが課金されます。残高がゼロに達すると、そのアカウントは削除されます。
ベストプラクティス: 予期しないアカウント削除を避けるため、データアカウントには常にレント免除の最低額を上回る資金を入れておいてください。
コンピュートバジェット
各命令の実行は、コンピュートユニットで計測されます:
| パラメータ | 値 |
|---|---|
| 命令あたりの最大コンピュートユニット | 1,400,000 |
| 最大CPI(クロスプログラム呼び出し)深度 | 4 |
| 最大プログラムサイズ | 10 MB |
| 最大アカウントデータサイズ | 10 MB |
コンピュートバジェットを超過したプログラムは停止され、トランザクションはリバートされます。
パラメータまとめ
| パラメータ | 値 |
|---|---|
max_program_size | 10 MB |
max_account_data_size | 10 MB |
compute_budget_max | 1,400,000 CU |
max_cpi_depth | 4 |
lamports_per_byte_year | 3,480 |
rent_exemption_multiplier | 2.0 |
| JSON-RPCポート | 8899 |
クロスVM相互運用性
SVMプログラムは、非同期のクロスVMメッセージパスを通じてEVMおよびCosmWasmコントラクトと通信できます:
# Cross-VM call example
qorechaind tx crossvm call \
--source-vm svm \
--target-vm evm \
--target-contract 0x1234...abcd \
--payload '...' \
--from mykey \
-y
メッセージはキューに入れられ、EndBlockerによって処理されます。メッセージのライフサイクルとタイムアウトの挙動の詳細については、クロスVM相互運用性を参照してください。
次のステップ
- クロスVM相互運用性 — SVM、EVM、CosmWasm間の通信
- EVM開発 — QoreChain上のSolidityスマートコントラクト
- CosmWasm開発 — Rustベースのwasmコントラクト