Derivando PDAs
PDAs são derivadas de seeds e um program id. find_program_address retorna o endereço canônico off-curve e a seed de bump exigida para invoke_signed.
Receita
let (pda, bump) = Pubkey::find_program_address(
&[b"metadata", mint.key.as_ref()],
program_id,
);Quando usar:
- Computar endereços em clientes antes de enviar transações.
- Verificar PDAs fornecidas pelo cliente on-chain.
- Projetar esquemas de seeds multi-tenant.
Exemplo Prático
pub fn verify_config(config: &AccountInfo, authority: &Pubkey, program_id: &Pubkey, stored_bump: u8) -> ProgramResult {
let (expected, bump) = Pubkey::find_program_address(&[b"config", authority.as_ref()], program_id);
if expected != *config.key || bump != stored_bump {
return Err(ProgramError::InvalidSeeds);
}
Ok(())
}O que isso demonstra:
- Inclui pubkey de autoridade nas seeds para configs por usuário.
- Compara chave derivada e bump com valores armazenados.
- Retorna
InvalidSeedsem caso de incompatibilidade.
Aprofundamento
Algoritmo
- Hash seeds + program id + bump até encontrar ponto off-curve.
- Bump canônico é o válido mais alto (255 para baixo).
Limites de Seeds
| Restrição | Valor |
|---|---|
| Contagem de seeds | <= 16 |
| Tamanho da seed | <= 32 bytes cada |
Notas Rust
let bump_seed = [bump];
let signer_seeds: &[&[u8]] = &[b"vault", owner.as_ref(), &bump_seed];Erros Comuns
- Program id errado no cliente - Deriva endereço diferente. Correção: Passe program id da chave implantada.
- Bump ausente nas seeds -
invoke_signedfalha. Correção: Anexe slice&[bump]. - Seeds de string UTF-8 - Use
.as_bytes()consistentemente. Correção: Documente a codificação. - u64 nas seeds - Use bytes fixed-endian:
id.to_le_bytes(). Correção: Evite empacotamento ambíguo. - Re-derivar sempre - Desperdiça CU on-chain. Correção: Armazene bump canônico.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| create_program_address | Bump conhecido | Bump desconhecido |
| Macro seeds do Anchor | Ergonômico | Nativo explícito |
| Derivação só off-chain | Economiza CU | Deve verificar on-chain |
FAQs
find vs create?
find busca bump; create exige bump exato.
Mesmas seeds em programas diferentes?
PDAs diferentes - por design.
Seeds vazias permitidas?
Desencorajado - use prefixo constante.
Ordem de seed de pubkey?
Documente; mudar ordem muda endereço.
Bump sempre 255?
Não garantido - armazene bump real.
Derivação TS no cliente?
@solana/kit getProgramDerivedAddress.
Vetores de teste?
Snapshot pda+bump nos testes.
Colisão de seeds?
Semânticas diferentes precisam prefixos diferentes.
Upgrade muda PDA?
Não se program id inalterado.
Múltiplas PDAs por usuário?
Adicione bytes de disambiguador nas seeds.
Máximo de seeds?
16 seeds por derivação.
Custo de busca on-chain?
Evite - use bump armazenado.
Relacionado
- Noções Básicas de PDA - Introdução
- Bumps Canônicos - Armazenar bump
- Assinando com PDAs - invoke_signed
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.