Trabajando con Pubkeys y Cuentas
Pubkey identifica cuentas y programas. AccountInfo es el manejador en tiempo de ejecución para lamports, datos, propietario y banderas de firmante. Un slicing y validación correctos previenen la escalada de privilegios.
Receta
use solana_program::{account_info::AccountInfo, pubkey::Pubkey};
fn assert_signer(ai: &AccountInfo) -> ProgramResult {
if !ai.is_signer { return Err(ProgramError::MissingRequiredSignature); }
Ok(())
}Cuándo usar esto:
- Validando listas de cuentas suministradas por el cliente en programas nativos.
- Comparando propietarios, PDAs e IDs de programa.
- Iterando cuentas con
next_account_info.
Ejemplo de Trabajo
use solana_program::{
account_info::{next_account_info, AccountInfo},
program_error::ProgramError,
pubkey::Pubkey,
};
pub fn process_transfer(accounts: &[AccountInfo], expected_owner: &Pubkey) -> ProgramResult {
let iter = &mut accounts.iter();
let payer = next_account_info(iter)?;
let vault = next_account_info(iter)?;
if !payer.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
if vault.owner != expected_owner {
return Err(ProgramError::IncorrectProgramId);
}
if !vault.is_writable {
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}Lo que esto demuestra:
- Las banderas de firmante y escribible se imponen explícitamente.
- La comprobación del propietario vincula la bóveda a tu programa.
next_account_infoavanza el iterador de cuentas en el orden del cliente.
Análisis Profundo
Campos de AccountInfo
| Campo | Significado |
|---|---|
key | Dirección de la cuenta |
lamports | Referencia al saldo de SOL |
data | Referencia al payload de bytes |
owner | Programa que puede escribir datos |
is_signer | Firmó esta transacción |
is_writable | Modificable en esta transacción |
Consejos sobre Pubkey
- Compara con
==en referencias. - Las PDAs tienen
is_on_curve == falsefuera de la cadena; en la cadena trátalas como claves normales.
Notas de Rust
let (pda, bump) = Pubkey::find_program_address(&[b"vault", owner.as_ref()], program_id);Errores Comunes
- Desfase en el orden de las cuentas - El cliente reordena y pasa la cuenta incorrecta para la comprobación. Solución: Documenta el orden fijo; usa restricciones de Anchor o índices explícitos.
- PDA sin verificar - Deriva el bump en la cadena y compáralo con el bump canónico almacenado. Solución: Ver la página de Bumps Canónicos.
- Cuentas duplicadas - Pasar la misma clave dos veces puede eludir las comprobaciones de débito/crédito. Solución: Rechaza claves duplicadas en instrucciones sensibles.
- Propietario vs. clave - Comprobar
keycuando se pretendíaownerpermite la suplantación. Solución: Nombra las variables claramente y revisa el linting. - Lamports mut sin firmante - Para debitar SOL se requiere un firmante o autoridad de PDA. Solución: Valida el firmante antes de los cambios de
**lamports.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
Anchor Account<'info, T> | Comprobaciones automáticas de propietario/discriminador | Control manual |
Pinocchio AccountView | Análisis de cuentas de menor CU | Madurez del ecosistema |
| Mapas de cuentas fuera de la cadena | El cliente construye metadatos de cuenta | La cadena aún debe verificar |
Preguntas Frecuentes
¿Cuál es la vida útil de AccountInfo?
Vinculada a la instrucción; no almacenes referencias entre CPI.
¿Puede key ser una PDA?
Sí; las PDAs son pubkeys fuera de la curva ed25519.
¿Cómo comparar Pubkey?
Usa ==; no hay requisito de tiempo constante para las pubkeys.
¿Leer lamports?
Usa **account.lamports o helpers de préstamo.
¿Quién establece is_writable?
El constructor de transacciones; el programa debe afirmarlo por seguridad.
¿Datos de cuenta vacíos?
Las cuentas no inicializadas pueden tener longitud cero hasta que se asignan.
¿Propietario del programa del sistema?
Las nuevas cuentas son propiedad del Programa del Sistema hasta que se asignan.
¿Pueden firmar los programas?
Solo a través de PDAs con invoke_signed.
¿Pubkey desde cadena?
Fuera de la cadena Pubkey::from_str; en la cadena recibe como clave de cuenta.
¿Slicing de cuentas?
Usa el patrón de iterador; evita longitudes codificadas sin comprobaciones.
¿Bandera ejecutable?
Las cuentas de programa son ejecutables; las cuentas de datos no lo son.
¿Exento de alquiler?
Comprueba Rent::get()?.is_exempt al crear cuentas.
Relacionado
- Validación Manual de Cuentas - Lista de verificación completa
- Derivación de PDAs - Direcciones PDA
- Conceptos Básicos de PDA - Por qué existen las PDAs
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.