no_std y el Entorno del Programa
Los programas de Solana compilan a SBF y se ejecutan en un entorno aislado sin std. Tienes las llamadas al sistema solana_program, alloc opcional y un presupuesto estricto de CUs.
Receta
#![no_std]
extern crate alloc;
use solana_program::{
account_info::AccountInfo, entrypoint, program_error::ProgramError,
pubkey::Pubkey,
};Cuándo recurrir a esto:
- Al iniciar cualquier crate de programa nativo (no Anchor).
- Al auditar por qué una dependencia falla al compilar para
cargo build-sbf. - Al elegir entre colecciones de
allocy diseños de cuentas de tamaño fijo.
Ejemplo de Trabajo
#![no_std]
extern crate alloc;
use alloc::vec::Vec;
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
program_error::ProgramError, pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
if instruction_data.is_empty() {
return Err(ProgramError::InvalidInstructionData);
}
let _owner = accounts.get(0).ok_or(ProgramError::NotEnoughAccountKeys)?;
let buf: Vec<u8> = instruction_data.to_vec();
solana_program::msg!("bytes: {}", buf.len());
Ok(())
}Lo que esto demuestra:
#![no_std]junto conextern crate alloces la disposición predeterminada del programa nativo.- Los datos de la instrucción llegan como un slice de bytes; cópialos solo cuando sea necesaria la mutación.
- El acceso a las cuentas se realiza a través de referencias
AccountInfoproporcionadas por el runtime.
Análisis Profundo
Cómo Funciona
- El runtime Agave 4.1.1 carga tu
.soe invoca el símbolo registrado porentrypoint!. - Las llamadas al sistema (registro, CPI, préstamo de cuentas) son la única forma de interactuar con el estado de la cadena.
- Los
panicabortan la instrucción; no hay desenrollado (unwinding) a través del límite del host.
Crates Disponibles
| Capa | Ejemplos | Notas |
|---|---|---|
| Núcleo | solana_program | Cuentas, CPI, sysvars, errores |
| Serialización | borsh, bytemuck | Diseños de instrucciones y cuentas |
| Matemáticas | num-traits, operaciones verificadas | Evita las matemáticas de std |
| Evitar | std, tokio, reqwest | No compilará para SBF |
Notas de Rust
// Prefiere &[u8] sobre Vec a menos que necesites poseer los bytes.
// solana_program reexporta Pubkey, ProgramError y sysvars.Trampas
- Importar std - Añadir un crate que importe
stdrompecargo build-sbf.. Solución: Fija las dependencias concargo treey prefiere crates compatibles conno_std. - Agitación del heap -
Vec::pushen rutas críticas asigna y cuesta CUs.. Solución: Usa tamaños de cuenta fijos o arrays en la pila con límites conocidos. - Panic al parsear -
unwrapen datos incorrectos del cliente aborta toda la transacción.. Solución: DevuelveProgramError::InvalidAccountDataen su lugar. - Falta de alloc - Usar
Vecsinextern crate allocfalla al enlazar.. Solución: Añadeextern crate allocen la raíz del crate. - Impresiones de depuración -
println!no está disponible en la cadena.. Solución: Usamsg!o errores personalizados con moderación.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Anchor 0.32.1 | Iteración más rápida con macros de cuenta | Máxima eficiencia de CU/binario |
| Pinocchio | Puntos de entrada sin dependencias | Necesitas la ergonomía de Anchor |
| Solo bytemuck | Diseños fijos grandes | Cadenas de longitud variable |
Preguntas Frecuentes
¿Puedo usar colecciones de std en la cadena?
No std. Usa alloc (Vec, String) o almacena datos en cuentas.
¿Qué sucede en caso de panic?
La instrucción falla y no se confirman cambios de estado.
¿Cómo imprimo información de depuración?
Usa msg! - cuesta CUs y aparece en los registros de transacciones.
¿Está disponible la ejecución de hilos (threading)?
No. Ejecución de un solo hilo por instrucción.
¿Pueden los programas leer el sistema de archivos?
No hay E/S más allá de los datos de la cuenta y las llamadas al sistema.
¿Por qué `extern crate alloc`?
Habilita la asignación de memoria dinámica a través del asignador del programa.
¿Qué es SBF?
Solana Bytecode Format - el objetivo en cadena (sucesor de BPF).
¿Cómo pruebo código no-std?
Usa #[cfg(test)] en el host con solana-program-test o LiteSVM 0.6.x.
¿Puedo usar async/await?
No hay runtime asíncrono en cadena.
¿Qué sysvars existen?
Clock, Rent, Instructions - se leen a través de los módulos sysvar.
¿Qué tan grande puede ser la pila?
Mantén el uso de la pila pequeño; el estado grande pertenece a las cuentas.
¿Funciona `format!`?
Asigna mucha memoria; evítalo en rutas de producción.
Relacionado
- Fundamentos de Rust para Solana - Orientación de la sección
- Serialización Borsh - Codificación de datos
- Disciplina de Tamaño de Programa y CU - Rendimiento
Versiones de la pila: Esta página fue escrita 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.