LiteSVM
LiteSVM 0.6.x ejecuta una VM de Solana en proceso para pruebas de programas en menos de un segundo sin solana-test-validator. Úsalo para pruebas unitarias, casos negativos de seguridad y bucles de retroalimentación de Rust rápidos.
Receta
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
use litesvm::LiteSVM;
use solana_sdk::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
signature::Keypair,
signer::Signer,
transaction::Transaction,
};
let mut svm = LiteSVM::new();
let payer = Keypair::new();
svm.airdrop(&payer.pubkey(), 10_000_000_000).unwrap();
svm.add_program(program_id, include_bytes!("../target/deploy/my_program.so"));Cuándo usar esto:
- Pruebas de manejadores de instrucciones en Rust puro
#[test]. - Fuzzing rápido de metadatos de cuentas adversarias.
- Capa de pruebas unitarias de CI antes de un
anchor testmás lento. - Depuración de errores de programas sin el ruido de RPC.
Ejemplo de trabajo
use litesvm::LiteSVM;
use solana_sdk::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
signature::Keypair,
signer::Signer,
system_program,
transaction::Transaction,
};
#[test]
fn withdraw_requires_signer() {
let program_id = Pubkey::new_unique();
let mut svm = LiteSVM::new();
svm.add_program(program_id, include_bytes!("../target/deploy/my_program.so"));
let payer = Keypair::new();
svm.airdrop(&payer.pubkey(), 2_000_000_000).unwrap();
let vault = Pubkey::new_unique();
let ix = Instruction {
program_id,
accounts: vec![
AccountMeta::new(vault, false),
AccountMeta::new_readonly(payer.pubkey(), false), // falta firmante
],
data: vec![1, 0, 0, 0], // marcador de posición del discriminador de retiro
};
let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&payer.pubkey()),
&[&payer],
svm.latest_blockhash(),
);
let result = svm.send_transaction(tx);
assert!(result.is_err());
}Lo que esto demuestra:
- Carga de
.socompilado directamente en LiteSVM. - Construcción de transacciones con metadatos de cuenta explícitos para casos de ataque.
- Afirmación de fallo sin iniciar un validador o un framework de TypeScript.
Inmersión Profunda
Cómo funciona
- LiteSVM integra la ejecución de SVM en tu proceso de prueba.
- Sysvars, rent y el comportamiento del cargador BPF aproximan la semántica de Agave 4.1.1.
- Blockhash y clock se pueden avanzar manualmente para pruebas dependientes del tiempo.
- Sin RPC: las pruebas se ejecutan completamente en memoria.
LiteSVM vs. Otros Frameworks
| Herramienta | Velocidad | Fidelidad | Idioma |
|---|---|---|---|
| LiteSVM 0.6.x | Más rápido | Alto para la lógica de ix | Rust |
| Mollusk | Rápido | Enfocado en instrucciones | Rust |
| Bankrun | Rápido | Ergonomía de TS | TypeScript |
| test-validator | Lento | RPC completo | Cualquiera |
Notas de Rust
// Avanzar el reloj para pruebas de obsolescencia
svm.set_sysvar(&solana_sdk::clock::Clock {
unix_timestamp: 1_700_000_000,
..Default::default()
});Trampas
- Artefacto
.soobsoleto - La prueba ejecuta una binario antigua después de un cambio de código. Solución:anchor builden CI antes decargo test. - Programas faltantes en svm - CPI a SPL Token falla sin cargar el programa de token. Solución:
svm.add_programpara dependencias. - Configuración de datos de cuenta - Las cuentas no inicializadas requieren empaquetado de datos manual. Solución: Ayudante para escribir diseños Borsh/Anchor en cuentas svm.
- Blockhash expirado - Las secuencias de prueba largas requieren
svm.expire_blockhash()o actualización. Solución: Obtenerlatest_blockhash()por tx. - Conflicto de características - Las características de compilación difieren de las de implementación. Solución: Mismas características de
Cargo.tomlque la compilación de lanzamiento. - No es RPC completo - Las peculiaridades específicas de RPC requieren pruebas de validador. Solución: Capa de pruebas E2E por separado.
Alternativas
| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
| Mollusk | Solo Rust a nivel de instrucción | Quieres ergonomía completa de simulación de tx |
| Bankrun | Equipo de TypeScript | Flujo de trabajo puro de Rust |
| anchor test | Integración completa | Velocidad del bucle interno |
Preguntas frecuentes
¿Qué versión de LiteSVM coincide con Agave 4.1.1?
Fija LiteSVM 0.6.x por manifiesto; verifica las notas de la versión para compatibilidad de syscalls.
¿Puede LiteSVM probar CPIs?
Sí: carga los programas llamados (Token, tu bóveda) y proporciona el grafo de cuentas correcto.
¿Cómo financio cuentas?
svm.airdrop para SOL; establece manualmente los datos de la cuenta de token para saldos de SPL.
¿Funciona Anchor con LiteSVM?
Usa .so crudo + datos de instrucción, o ayudantes de la comunidad para construir discriminadores de Anchor.
¿Integración CI?
cargo test después de anchor build - no se requiere servicio de validador para la capa LiteSVM.
¿Cómo pruebo firmantes PDA?
Incluye la cuenta PDA correcta con is_signer: false; el programa invoca CPI firmada internamente.
¿Hay registros disponibles?
Las transacciones fallidas devuelven registros en el error - afirma subcadenas de registro para depuración personalizada de msg!.
¿Pruebas paralelas?
Cada prueba debe poseer LiteSVM::new() - evita compartir svm mutables entre hilos.
¿IDs de programa de Devnet?
Usa los mismos IDs de programa que el clúster de destino al probar listas de permitidos de CPI.
¿Cuándo pasar a las pruebas de validador?
Al depender de métodos RPC, ALTs o comportamiento de aterrizaje de transacciones múltiples.
Relacionado
- Conceptos básicos de pruebas - contexto de la pirámide
- Mollusk - framework alternativo de Rust
- Pruebas de CPI y PDA - patrones de prueba de CPI
- Mejores prácticas de seguridad - pruebas negativas
Versiones de la pila: Esta página se escribió para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, y LiteSVM 0.6.x.