Rust para Programas de Solana
El código en cadena de Solana es Rust, pero no es Rust de portátil con un main diferente. Compilas a sBPF, ejecutas dentro del SVM, y solo tocas el estado de la cadena a través de cuentas y llamadas al sistema.
Busca en todas las páginas de la documentación
El código en cadena de Solana es Rust, pero no es Rust de portátil con un main diferente. Compilas a sBPF, ejecutas dentro del SVM, y solo tocas el estado de la cadena a través de cuentas y llamadas al sistema.
Ese subconjunto - no_std, asignación restringida, un punto de entrada fijo, diseños Borsh (o zero-copy), matemáticas verificadas, errores tipados y presupuestos de cómputo/tamaño - es el lenguaje de cada programa nativo, Anchor y ligero en Agave 4.1.1.
no_std: un punto de entrada, datos de instrucción y cuenta a nivel de byte (generalmente Borsh), aritmética segura, errores de fallo rápido y límites estrictos en unidades de cómputo y tamaño binario.unwrap, crecimiento ilimitado de Vec, dependencias std, desbordamiento silencioso, registro excesivo) o no compilan para cargo build-sbf o pasan las pruebas y luego fallan bajo presión de CU, alquiler y auditoría en mainnet-beta.El código fuente de los programas de Solana es Rust 1.91.1 (el pin de este sitio), pero el target no es un triple de host.
cargo build-sbf (a través de las herramientas de la plataforma Agave / compilación de Anchor) compila cruzado a sBPF (Solana Bytecode Format). Los validadores cargan el .so y el SVM lo ejecuta bajo los bloqueos de Sealevel y la medición de cómputo.
No hay un main de proceso. El cargador invoca un único punto de entrada que el crate registra (nativo entrypoint!, o el despachador generado por Anchor). Esa función recibe program_id, un slice de AccountInfo, y bytes de instruction_data. Las variantes de instrucción, los diseños de cuenta, los PDA y las CPI se basan en ese triple.
El entorno es no_std: sin sistema de archivos, sockets, hilos o biblioteca estándar completa. alloc opcional proporciona Vec / String / Box, pero el uso del heap cuesta cómputo. El código de producción prefiere cuentas de tamaño fijo, análisis de pila y evitar format! en rutas críticas.
El estado duradero no vive en el binario del programa. Los registros de la aplicación residen en cuentas que el programa posee (o que otros programas poseen, mutadas solo a través de CPI). Las estructuras de Rust en cadena son esquemas sobre bytes de cuenta.
Borsh es la codificación de facto para instrucciones y la mayoría de las estructuras de cuenta (predeterminado de Anchor 0.32.1). Los diseños grandes y fijos a menudo usan bytemuck zero-copy en su lugar. El dinero y los contadores usan u64 (o enteros fijos más anchos) con operaciones verificadas. Los fallos devuelven ProgramError (o códigos personalizados mapeados); prefiera ? sobre unwrap. La ejecución se mide en unidades de cómputo, y el tamaño binario afecta el costo de despliegue. "Compila" no significa "encaja en los presupuestos de CU y tamaño".
Los crates nativos dependen de solana-program (o Pinocchio). Los proyectos de Anchor usan anchor-lang = "0.32.1" para la generación del punto de entrada y la validación de cuentas.
Flujo de compilación: compilar a sBPF ELF con herramientas de plataforma, desplegar con Solana CLI 3.0.10 / Anchor, almacenar el bytecode en ProgramData bajo el cargador actualizable, y luego en cada instrucción el SVM mapea cuentas, llama al punto de entrada, mide CU y confirma o revierte.
Las pruebas unitarias del host (#[cfg(test)]) se ejecutan en la estación de trabajo; las pruebas de integración usan LiteSVM 0.6.x, Surfpool 0.12.0, o un validador local.
Estilo nativo:
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// decodificar instruction_data, validar cuentas, mutar estado propio
Ok(())
}Dentro del manejador generalmente:
next_account_info o verificaciones de índiceOk(()) o Err(...)Anchor envuelve esto en módulos #[program] y discriminadores de 8 bytes. El modelo de tiempo de ejecución no cambia: un punto de entrada, cuentas declaradas, datos de bytes.
En cadena obtienes core, crates no_std seleccionados, llamadas al sistema solana_program (log, CPI, sysvars), alloc opcional y serializadores como Borsh / bytemuck que compilan para sBPF.
No obtienes std completo, tiempos de ejecución asíncronos, clientes HTTP o acceso al sistema de archivos. Si cargo build-sbf falla en una dependencia, audita cargo tree para dependencias std transitivas y cambia a crates seguros para programas.
Los datos de instrucción y los cuerpos de cuenta son bytes. Borsh es determinista y little-endian: enteros fijos, bool de 1 byte, Pubkey de 32 bytes, Vec/String prefijados con u32, y discriminadores de enum.
Tamaño de las cuentas en la creación para que el serializador no pueda escribir más allá de account.data.len(). Los cambios de esquema requieren versionado o migraciones; reordenar variantes de enum cambia silenciosamente las etiquetas. Zero-copy (Pod + Zeroable + #[repr(C)]) reinterpreta cuentas grandes y fijas sin una copia completa cuando CU es importante.
Las cantidades de tokens, las tarifas en puntos básicos, las matemáticas de acciones y los índices de recompensas deben usar:
let next = balance
.checked_add(amount)
.ok_or(ProgramError::InvalidArgument)?;Prefiera checked_* cuando el desbordamiento sea un error, saturating_* cuando un límite sea intencional, y verificaciones de límites explícitas para reglas de negocio (suministro máximo, bps máximos). No confíe en los pánicos de desbordamiento solo de depuración; trate el desbordamiento como un fallo de diseño.
ProgramResult es Result<(), ProgramError>. Mapee fallos de dominio a códigos personalizados (implementaciones From nativas, #[error_code] de Anchor, o similar) para que los clientes TypeScript con @solana/kit 7.0.0 puedan ramificarse en números de error en lugar de solo raspar registros.
Use msg! con moderación para diagnósticos. Los registros cuestan CU y no son un sustituto de los errores estructurados en rutas de fallo esperadas (no autorizado, deslizamiento, caducado).
CU se extrae de un presupuesto a nivel de transacción (en Solana moderno, incluido Agave 4.1.1, planifique alrededor de un valor predeterminado cercano a 1,400,000 CU a menos que las instrucciones de Compute Budget cambien el límite dentro de los máximos del protocolo).
Sumideros comunes de CU:
msg! verboso en bucles ajustadosSumideros de tamaño binario:
La disciplina significa retornos tempranos, iteración acotada, dependencias ligeras y perfilado con simulación antes del tráfico de mainnet-beta.
| Enfoque | Experiencia Rust | CU / tamaño | Cuándo encaja |
|---|---|---|---|
| Anchor 0.32.1 | Macros, cuentas, IDL | Línea de base más alta | Velocidad de producto, clientes tipados |
solana-program nativo | Punto de entrada y verificaciones explícitas | Techo más bajo si se tiene cuidado | Aprendizaje, cargadores de control personalizados |
| Pinocchio / pilas delgadas | Orientado a sistemas | A menudo el más ligero | Rutas críticas, programas de infraestructura |
| Híbrido | Capa de aplicación Anchor + núcleo delgado | Dividido por CPI | Sistemas maduros con puntos críticos medidos |
Los tres todavía obedecen las restricciones de no_std, los diseños Borsh o bytes, la aritmética verificada y la medición de CU. La elección del framework cambia las macros y la ergonomía de validación, no las reglas de Sealevel.
| Hábito de Rust del host | Sustituto en cadena |
|---|---|
main + argumentos CLI | Punto de entrada + bytes de instrucción + lista de cuentas |
| Archivos / filas de DB | Cuentas propiedad del programa con diseños fijos o versionados |
anyhow + rastreos de pila | Códigos ProgramError compactos + registros selectivos |
Crecimiento ilimitado de Vec | Capacidad fija, almacenamiento respaldado por cuenta, recuentos máximos |
| Hilos / async | Instrucción de un solo hilo; la paralelización es Sealevel entre transacciones |
println! | msg! (medido) |
| Dinero flotante | Lamports enteros / unidades base de token + operaciones verificadas |
Use encabezados de cuenta versionados, discriminadores (etiquetas manuales o de 8 bytes de Anchor), semillas de PDA como parte de la API, y ayudantes de CPI que aún requieren cuentas declaradas. Mantenga las pruebas solo del host detrás de cfg para que no inflen el binario sBPF.
Pruebe unitariamente matemáticas puras y empaquetado en el host. Ejecute instrucciones completas bajo LiteSVM 0.6.x o Surfpool 0.12.0. Mida el tamaño binario después de la compilación y computeUnitsConsumed de la simulación (los metadatos de Kit RPC son suficientes para verificaciones del lado del cliente).
no_std con alloc opcional; la mayoría de las pilas std y asíncronas no compilarán para sBPF.unwrap está bien si los clientes son honestos." Los clientes son adversarios; los pánicos desperdician CU y producen una experiencia de usuario del cliente peor que los errores tipados.msg! puede hacer que las rutas superen el presupuesto de CU; prefiera errores y indexación fuera de cadena para eventos de alto volumen.repr(C)/Pod; los campos de longitud variable a menudo favorecen Borsh.sBPF bytecode (ELF .so) ejecutado por el SVM en los validadores de Agave. Compilas con cargo build-sbf o la compilación de Anchor, no solo con un target de host normal.
El cargador BPF/SBF llama al punto de entrada registrado para cada instrucción. Los frameworks generan o envuelven ese punto de entrada por usted.
no_std elimina la biblioteca estándar. alloc restaura opcionalmente tipos de heap (Vec, String) a través del asignador del programa, todavía sin E/S del sistema operativo o hilos. Prefiera diseños fijos cuando sea posible.
Sí. Anchor 0.32.1 emite Rust que apunta al mismo tiempo de ejecución. Las macros reducen el código repetitivo para cuentas, errores e IDL; no cambian las reglas de Sealevel.
Es determinista, compacto y compartido entre programas nativos, predeterminados de Anchor y muchos codificadores de cliente. La estabilidad entre lenguajes importa más que usar cualquier formato serde que le guste en el host.
Cuando las cuentas son grandes, de tamaño fijo y lo suficientemente críticas como para que la deserialización/serialización completa domine la CU. Mantenga las reglas de alineación y relleno bajo revisión.
Sí. La suma, la multiplicación de tarifas y las matemáticas de acciones aún pueden desbordar u64. Las operaciones verificadas convierten eso en un fallo de instrucción limpio.
Mapee códigos de error personalizados en el programa y decodifíquelos fuera de cadena (tablas de IDL/errores con Anchor, o códigos documentados para nativos). Use metadatos de transacción de @solana/kit 7.0.0 para registros y campos de error.
Elimine registros de rutas críticas, limite bucles, evite clonar búferes de bytes grandes, deserialice solo los campos necesarios y simule con tamaños de cuenta realistas.
Debe compilar bajo cargo build-sbf, preferiblemente como no_std. Verifique las dependencias transitivas para características solo de std y prefiera crates mantenidos para programas de Solana.
Prefiera punto fijo entero para saldos, tarifas y acciones. Evite los flotantes para cualquier cosa financiera.
Las páginas de Sealevel cubren bloqueos, paralelismo y medición. Esta sección cubre el subconjunto de Rust que escribe dentro de ese tiempo de ejecución.
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, LiteSVM 0.6.x.
Esta descripción general, luego Fundamentos de Rust para Solana, luego las páginas de no_std, Borsh, aritmética, errores y CU a medida que construye.
Adelgaza las dependencias y el estilo del punto de entrada. Todavía razonas sobre cuentas, bytes, errores y CU de la misma manera.
?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.
Revisado por Chris St. John·Última actualización: 15 jul 2026