Lendo e Escrevendo Dados de Conta
Dados de conta vivem em um buffer de bytes gerenciado pelo runtime. Programas fazem borrow imutável ou mutável, parse em tipos, mutam e escrevem de volta com Borsh ou updates zero-copy.
Receita
let mut data = account.try_borrow_mut_data()?;
let state = State::deserialize(&mut &data[..])?;Quando usar:
- Atualizar contadores, config ou state do usuário.
- Ler campos de conta SPL token (via layout spl-token).
- Migrar layouts de conta em instructions de upgrade.
Exemplo Funcional
pub fn increment(account: &AccountInfo) -> ProgramResult {
if account.data_len() < State::LEN { return Err(ProgramError::InvalidAccountData); }
let mut data = account.try_borrow_mut_data()?;
let mut state = State::deserialize(&mut &data.as_ref()).map_err(|_| ProgramError::InvalidAccountData)?;
state.count = state.count.checked_add(1).ok_or(ProgramError::InvalidArgument)?;
state.serialize(&mut &mut data.as_mut()).map_err(|_| ProgramError::AccountDataTooSmall)?;
Ok(())
}O que isso demonstra:
- Guarda de comprimento antes de deserialize.
try_borrow_mut_datapara writes.- Mapeie erros de serialize para
AccountDataTooSmall.
Aprofundamento
Regras de Borrow
- Um borrow mutável OU vários imutáveis.
- Libere borrows antes de CPI na mesma conta.
Updates Parciais
Zero-copy permite mutação de campo sem serialize completo.
Notas Rust
// Prefira subslices &mut [u8] para discriminator + body.Erros Comuns
- Borrow através de CPI - Erro/panic do runtime.. Correção: Encerre borrow antes de invoke.
- Layout obsoleto - Deserialize struct antiga no programa novo.. Correção: Byte de versão + migração.
- Confusão de conta de token - Trate layout de token separado de State customizado.. Correção: Use pack/unpack spl-token.
- Resize sem realloc - Serialize falha se conta pequena demais.. Correção: CPI instruction realloc primeiro.
- Zero-copy desalinhado - UB em casts ruins.. Correção: Verifique tamanho e alinhamento.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Update de campo bytemuck | Contadores em hot path | Strings variáveis |
| Anchor Account::try_from | Owner/discriminator automático | Nativo |
| Views read-only | Pinocchio | Ecossistema |
FAQs
try_borrow vs borrow?
Use variantes try_ em programas - falhe graciosamente.
Quem pode escrever?
Apenas o programa owner da conta.
Ler contas de outros?
Sim se passadas na transação - valide owner.
Data vazio?
Não inicializado - rejeite ou caminho init.
Tamanho máximo de write?
Espaço alocado da conta.
Txs concorrentes?
Runtime serializa por conta por tx.
Logar bytes de data?
Evite - vaza info do usuário.
Close limpa data?
Zero lamports após close - zere data primeiro.
realloc?
Veja artigo realloc.
Rent após crescer?
Mais bytes precisam de mais lamports.
Ler data de sysvar?
Use tipos sysvar dedicados.
Testes?
LiteSVM com fixtures de conta.
Relacionado
- Structs Borsh - Layouts
- realloc e Contas em Crescimento - Resize
- Discriminators de Conta - Tipagem
Versões do 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.