Solana 文档LiteSVMRust测试您的程序

执行指令

概述

将程序部署到 LiteSVM 后,您需要执行指令来与已部署的程序进行交互。

LiteSVM 提供了一套简单的 API,用于创建、发送和模拟交易,与 Solana 的交易模型完全兼容。

基本交易流程

执行指令的典型流程如下:

  1. 创建指令 - 定义要调用的程序及其数据
  2. 构建消息 - 将一条或多条指令组合在一起
  3. 创建交易 - 使用所需签名者对消息进行签名
  4. 发送或模拟 - 执行交易并处理结果

创建指令

基本指令结构

use solana_instruction::{Instruction, AccountMeta};
use solana_pubkey::Pubkey;
let instruction = Instruction {
program_id: Pubkey::new_unique(), // The program to call
accounts: vec![ // Accounts the program needs
AccountMeta::new(account_pubkey, false), // Writable, not signer
AccountMeta::new_readonly(readonly_pubkey, false), // Read-only, not signer
AccountMeta::new(signer_pubkey, true), // Writable, signer
],
data: vec![0, 1, 2, 3], // Instruction data (program-specific)
};

构建并发送交易

方法一:基本交易

use litesvm::LiteSVM;
use solana_keypair::Keypair;
use solana_message::Message;
use solana_transaction::Transaction;
use solana_signer::Signer;
let mut svm = LiteSVM::new();
let payer = Keypair::new();
// Airdrop SOL for fees
svm.airdrop(&payer.pubkey(), 1_000_000_000).unwrap();
// Create instruction
let instruction = /* your instruction */;
// Build message with payer
let message = Message::new(&[instruction], Some(&payer.pubkey()));
// Create and sign transaction
let tx = Transaction::new_signed_with_payer(
&[instruction], // Your instructions
Some(&payer.pubkey()), // Who pays transaction fees
&[&payer], // All required signers
svm.latest_blockhash(), // Recent blockhash
);
// Send transaction
let result = svm.send_transaction(tx);

new_signed_with_payer 的作用:

  • 自动根据您的指令构建消息
  • 自动使用所有提供的 keypair 对交易进行签名
  • 返回已完整签名、可随时发送的交易

方法二:自定义消息交易

let payer = Keypair::new();
// Manually construct message
let message = Message::new(&[instruction], Some(&payer.pubkey()));
// Create transaction with signers, message, and blockhash
let tx = Transaction::new(
&[&payer],
message,
svm.latest_blockhash(),
);
let result = svm.send_transaction(tx);

当您需要控制 Message 时使用此方法,例如:

  • 版本化交易(带查找表的 v0)
  • 部分签名/多重签名工作流
  • 持久化 nonce
  • 签名前模拟或检查
  • 自定义手续费支付方逻辑
  • 交易大小优化

版本化交易

LiteSVM 同时支持传统交易和版本化交易:

use solana_transaction::versioned::VersionedTransaction;
use solana_message::VersionedMessage;
// Legacy transaction (most common)
let legacy_msg = Message::new(&[instruction], Some(&payer.pubkey()));
let versioned_tx = VersionedTransaction::try_new(
VersionedMessage::Legacy(legacy_msg),
&[&payer]
).unwrap();
// Send versioned transaction
let result = svm.send_transaction(versioned_tx);

交易结果

成功的交易

match svm.send_transaction(tx) {
Ok(meta) => {
println!("Signature: {}", meta.signature);
println!("Compute units: {}", meta.compute_units_consumed);
println!("Logs:");
for log in &meta.logs {
println!(" {}", log);
}
}
Err(err) => {
println!("Transaction failed: {:?}", err.err);
// Logs are still available on failure
println!("Failure logs: {:?}", err.meta.logs);
}
}

交易元数据字段

pub struct TransactionMetadata {
pub signature: Signature,
pub logs: Vec<String>,
pub inner_instructions: InnerInstructionsList,
pub compute_units_consumed: u64,
pub return_data: TransactionReturnData,
pub fee: u64,
}

模拟交易

模拟交易允许您在不改变状态的情况下测试交易:

// Simulate instead of sending
match svm.simulate_transaction(tx) {
Ok(sim_result) => {
println!("Simulation successful!");
println!("Logs: {:?}", sim_result.meta.logs);
println!("Compute units: {}", sim_result.meta.compute_units_consumed);
}
Err(err) => {
println!("Simulation failed: {:?}", err.err);
}
}

错误处理

常见交易错误

use solana_transaction_error::TransactionError;
use solana_instruction::error::InstructionError;
match svm.send_transaction(tx) {
Err(failed_tx) => {
match failed_tx.err {
TransactionError::InsufficientFundsForFee => {
println!("Not enough SOL for fees");
}
TransactionError::InvalidProgramForExecution => {
println!("Program doesn't exist or isn't executable");
}
TransactionError::InstructionError(index, err) => {
println!("Instruction {} failed: {:?}", index, err);
match err {
InstructionError::Custom(code) => {
println!("Custom error code: {}", code);
}
InstructionError::AccountNotFound => {
println!("An account doesn't exist");
}
_ => {}
}
}
TransactionError::BlockhashNotFound => {
println!("Blockhash expired or invalid");
}
_ => println!("Other error: {:?}", failed_tx.err),
}
}
Ok(_) => {}
}

使用程序日志

访问日志

let result = svm.send_transaction(tx).unwrap();
// All logs (including system logs)
for log in &result.logs {
println!("{}", log);
}
// Pretty-printed logs (formatted)
println!("{}", result.pretty_logs());

日志输出示例

Program 11111111111111111111111111111111 invoke [1]
Program log: Processing instruction
Program 11111111111111111111111111111111 consumed 2000 compute units
Program 11111111111111111111111111111111 success

计算预算配置

设置全局计算预算

use solana_compute_budget::compute_budget::ComputeBudget;
let mut svm = LiteSVM::new()
.with_compute_budget(ComputeBudget {
compute_unit_limit: 200_000,
..Default::default()
});

每笔交易的计算预算

use solana_compute_budget_interface::ComputeBudgetInstruction;
let instructions = vec![
// Set compute budget for this transaction
ComputeBudgetInstruction::set_compute_unit_limit(400_000),
ComputeBudgetInstruction::set_compute_unit_price(1),
// Your actual instruction
your_instruction,
];

System Program 指令

LiteSVM 包含 system program 支持:

use solana_keypair::Keypair;
use solana_signer::Signer;
use solana_system_interface::instruction as system_instruction;
use solana_transaction::Transaction;
// Transfer SOL
let transfer_ix = system_instruction::transfer(
&alice.pubkey(),
&bob.pubkey(),
1_000_000_000, // 1 SOL
);
// Create new account
let create_ix = system_instruction::create_account(
&payer_pubkey,
&new_account_pubkey,
lamports,
space as u64,
&owner_program_id,
);

总结

在 LiteSVM 中执行指令遵循标准的 Solana 交易模型:

  1. 使用程序 ID、账户和数据创建 Instruction 对象
  2. 使用指令和所需签名者构建 Transaction
  3. 使用 send_transaction() 执行,或使用 simulate_transaction() 进行测试
  4. 通过检查 TransactionMetadata 或错误详情来处理结果

LiteSVM 提供即时执行,并附带详细的日志和调试信息,非常适合高效测试 Solana 程序。

Is this page helpful?

©️ 2026 Solana 基金会版权所有