Trabalhando com Pubkeys e Contas
Pubkey identifica contas e programas. AccountInfo é o handle do runtime para lamports, dados, owner e flags de signer. Slicing e validação corretos previnem escalação de privilégio.
Receita
use solana_program::{account_info::AccountInfo, pubkey::Pubkey};
fn assert_signer(ai: &AccountInfo) -> ProgramResult {
if !ai.is_signer { return Err(ProgramError::MissingRequiredSignature); }
Ok(())
}Quando usar:
- Validar listas de contas fornecidas pelo cliente em programas nativos.
- Comparar owners, PDAs e IDs de programa.
- Iterar contas com
next_account_info.
Exemplo Funcional
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(())
}O que isso demonstra:
- Flags signer e writable são aplicadas explicitamente.
- Checagem de owner vincula o vault ao seu programa.
next_account_infoavança o iterador de contas na ordem do cliente.
Aprofundamento
Campos de AccountInfo
| Campo | Significado |
|---|---|
key | Endereço da conta |
lamports | Ref de saldo SOL |
data | Ref de payload de bytes |
owner | Programa que pode escrever dados |
is_signer | Assinou esta tx |
is_writable | Mutável nesta tx |
Dicas de Pubkey
- Compare com
==em referências. - PDAs têm
is_on_curve == falseoff-chain; on-chain trate como chaves normais.
Notas Rust
let (pda, bump) = Pubkey::find_program_address(&[b"vault", owner.as_ref()], program_id);Armadilhas
- Deriva de ordem de contas - Reordenação do cliente passa conta errada na checagem. Correção: Documente ordem fixa; use constraints Anchor ou índices explícitos.
- PDA não verificado - Derive bump on-chain e compare ao bump canônico armazenado. Correção: Veja página Canonical Bumps.
- Contas duplicadas - Mesma chave passada duas vezes pode burlar checagens de débito/crédito. Correção: Rejeite chaves duplicadas em instruções sensíveis.
- Owner vs key - Checar
keyquando quis dizerownerpermite impersonação. Correção: Nomeie variáveis claramente e faça lint em reviews. - Lamports mut sem signer - Debitar SOL exige signer ou autoridade PDA. Correção: Valide signer antes de mudanças em
**lamports.
Alternativas
| Alternativa | Use quando | Não use quando |
|---|---|---|
Anchor Account<'info, T> | Checagens auto de owner/discriminador | Controle manual |
Pinocchio AccountView | Parse de conta com CU menor | Maturidade do ecossistema |
| Maps de conta off-chain | Cliente monta account metas | On-chain ainda deve verificar |
FAQs
Qual é o lifetime de AccountInfo?
Amarrado à instrução - não armazene referências através de CPI.
Key pode ser PDA?
Sim - PDAs são pubkeys fora da curva ed25519.
Como comparar Pubkey?
Use ==; sem requisito constant-time para pubkeys.
Ler lamports?
Use **account.lamports ou helpers de borrow.
Quem define is_writable?
Construtor da transação - programa deve fazer assert por segurança.
Dados de conta vazios?
Contas não inicializadas podem ter comprimento zero até alocadas.
Owner System program?
Contas novas pertencem ao System Program até atribuídas.
Programas podem assinar?
Apenas via PDAs com invoke_signed.
Pubkey de string?
Off-chain Pubkey::from_str - on-chain receba como account key.
Slicing de conta?
Use padrão iterator; evite len hard-coded sem checagens.
Flag executable?
Contas de programa são executáveis; contas de dados não.
Rent exempt?
Verifique Rent::get()?.is_exempt ao criar contas.
Relacionado
- Manual Account Validation - Checklist completo
- Deriving PDAs - Endereços PDA
- PDA Basics - Por que PDAs existem
Versões da stack: Esta página foi 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 e LiteSVM 0.6.x.