El Punto de Entrada y Despacho
El punto de entrada es la única superficie RPC de tu programa. Dispatch analiza instruction_data, valida el contexto y enruta a los manejadores con semántica de error consistente.
Receta
entrypoint!(process_instruction);
let ix = MyInstruction::try_from_slice(data)?;
match ix { /* ... */ }Cuándo usar esto:
- Al construir programas nativos sin el despacho de Anchor.
- Al añadir una nueva variante de instrucción a un programa existente.
- Al auditar el análisis de instrucciones en busca de ambigüedad.
Ejemplo Funcional
use borsh::BorshDeserialize;
use solana_program::{account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, pubkey::Pubkey};
entrypoint!(process_instruction);
#[derive(BorshDeserialize)]
pub enum MyInstruction { Init, Increment }
pub fn process_instruction(program_id: &Pubkey, accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
if data.is_empty() { return Err(ProgramError::InvalidInstructionData); }
let ix = MyInstruction::deserialize(&mut &data[..]).map_err(|_| ProgramError::InvalidInstructionData)?;
match ix {
MyInstruction::Init => init(program_id, accounts),
MyInstruction::Increment => increment(program_id, accounts),
}
}Lo que esto demuestra:
- Guardia de datos vacíos antes de la deserialización.
- Mapeo de errores de análisis a
InvalidInstructionData. - Los manejadores reciben
program_idpara la derivación de PDA.
Análisis Profundo
Cómo Funciona
- El runtime pasa los bytes crudos de la instrucción de la transacción.
- El discriminante de la enumeración es el primer byte serializado, a menos que se utilicen etiquetas manuales.
- Cada manejador es responsable de la iteración de cuentas para su subconjunto.
Estilos de Despacho
| Estilo | Pros |
|---|---|
| Enumeración Borsh | Idiomático, compacto |
| Byte de opcode manual | Estilo C, versionado explícito |
#[program] de Anchor | IDL + restricciones automáticas |
Notas de Rust
// Mantén los manejadores ligeros; delega las comprobaciones compartidas a los validadores.Trampas Comunes
- Datos vacíos ambiguos - Tratados como una enumeración vacía válida en algunos diseños. Solución: Rechazar
data.is_empty()cuando no existe una instrucción predeterminada. - Reordenamiento de variantes - Rompe los clientes silenciosamente. Solución: Añadir variantes solo al final; versionar los cambios que rompen la compatibilidad.
- Brazos de
matchextensos - Los manejadores grandes oscurecen el rastro de auditoría. Solución: Una función por instrucción. - Falta
program_id- Los manejadores no pueden verificar PDAs. Solución: Pasarprogram_ida través de todas las rutas. unwrapsin verificar enslice- Pánicos por longitud incorrecta. Solución: Usar el mapeo deResultdedeserialize.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Despacho de Anchor | IDL + validación de cuentas | Binario mínimo |
| Punto de entrada Pinocchio | Menor sobrecarga | Ecosistema de macros |
| Tablas de opcodes | Programas estilo firmware | Enumeraciones simples |
Preguntas Frecuentes
¿Puedo tener múltiples puntos de entrada?
No, uno por binario de programa.
¿Dónde analizar las cuentas?
Dentro de cada manejador después del análisis de la cabecera compartida.
¿Prefijo de byte de versión?
Patrón común: el primer byte es la versión del esquema.
¿Compartir código con el cliente?
Publicar el crate de instrucciones para constructores de @solana/kit.
¿Probar el despacho?
Serializar bytes de ix en pruebas de LiteSVM.
¿Variante desconocida?
Borsh devuelve un error; mapearlo a InvalidInstructionData.
¿Cuentas opcionales?
Documentar y usar un centinela o instrucciones separadas.
¿Tamaño máximo de datos de instrucción?
Limitado por el tamaño de la transacción (aprox. 1232 bytes).
¿`entrypoint_no_alloc`?
Patrón avanzado para evitar el asignador en la entrada.
¿Análisis entre programas?
Nunca confíes en que la llamada de programa analice tus datos.
¿Registro en el despacho?
OK para desarrollo; evitar en la ruta crítica de producción.
¿Refactorizar `match` a tabla?
Usar punteros a funciones solo si el tamaño del binario es crítico.
Relacionado
- Conceptos Básicos de Programas Nativos - Estructura
- Serialización/Deserialización de Datos de Instrucción - Diseños
- Conceptos Básicos de CPI - Llamar a otros
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.