Serialización (de) de Datos de Instrucción
Los datos de instrucción son el contrato entre los clientes y tu programa. Los enums de Borsh son estándar; los opcodes manuales funcionan para un control estricto. Ambos requieren una disciplina de versionado estable.
Receta
#[derive(BorshSerialize, BorshDeserialize)]
pub enum MarketInstruction {
PlaceOrder { price: u64, qty: u64 },
}Cuándo usar esto:
- Al añadir parámetros a una instrucción.
- Al generar constructores de clientes @solana/kit 7.0.0.
- Al migrar el formato de instrucción entre actualizaciones.
Ejemplo Funcional
#[derive(BorshSerialize, BorshDeserialize)]
pub enum MarketInstruction {
PlaceOrder { price: u64, qty: u64 },
CancelOrder { order_id: u64 },
}
pub fn parse(data: &[u8]) -> Result<MarketInstruction, ProgramError> {
MarketInstruction::deserialize(&mut &data[..]).map_err(|_| ProgramError::InvalidInstructionData)
}Lo que esto demuestra:
- Las variantes llevan campos tipados.
- Una única función de análisis centraliza los errores.
- Los clientes reflejan el enum con el mismo
derive.
Análisis Profundo
Versionado
- Prefija
version: u8antes del cuerpo para cambios disruptivos. - Nunca reordenes las variantes de enum en programas en producción.
Paridad con el Cliente
Publica un crate instructions compartido por el programa y los clientes TS/Rust.
Notas de Rust
let data = ix.try_to_vec()?; // constructor fuera de la cadenaErrores Comunes
- String en datos de instrucción - Longitud ilimitada por el usuario. Solución: Limita los bytes de la cadena o usa claves fijas.
- Relleno implícito - Las estructuras manuales pueden desalinearse. Solución: Prefiere Borsh o
#[repr(C)]con cuidado. - Desfase del cliente - El SDK antiguo envía un diseño incorrecto. Solución: Controla versiones y documenta la migración.
Vecen la instrucción - Asigna memoria al analizar. Solución: Prefiere arrays fijos para rutas sensibles a CU.- Opcodes duplicados - Tablas manuales con colisiones. Solución: Centraliza las constantes.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Crate compartido + Codama | Clientes basados en IDL | Scripts rápidos |
Anchor #[program] | Serialización automática | Diseños personalizados |
| Tiras de bytes en bruto | Instrucción de un solo campo | Enums complejos |
Preguntas Frecuentes
¿Tamaño máximo de datos de instrucción?
Límites del paquete de transacciones: mantén las instrucciones pequeñas.
¿Discriminante `u8` suficiente?
Para <256 variantes, sí.
¿Precios `i64`?
Soportado: documenta el orden de los bytes (endianness).
¿`Pubkey` en instrucción?
32 bytes en Borsh.
¿Campos opcionales?
Usa Option<T> en Borsh.
¿Omitir el wrapper del enum?
Solo si el programa tiene una única instrucción.
¿Hashear el esquema de instrucción?
Úsalo para auditorías de actualización.
¿Fuzzing del análisis?
Recomendado en CI.
¿Discriminante inválido?
Devuelve un error de análisis.
¿Compatibilidad con Anchor?
Codificación diferente si se mezclan: evita.
¿JSON para instrucciones?
Solo fuera de la cadena; binario en la cadena.
¿Vectores de prueba?
Comprueba en fixtures hexadecimales.
Relacionado
- Serialización Borsh - Formato
- El Punto de Entrada y Despacho - Enrutamiento
- Construcción de Instrucciones - Clientes
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.