Aula 023: Trabalhando com Endereços Derivados de Programa (EDPs)
Nesta aula, vamos aprender sobre os Endereços Derivados de Programa (EDPs) no contexto da programação em Solana. Os EDPs são endereços únicos gerados por programas que permitem um armazenamento de dados seguro. Compreender como trabalhar com EDPs é crucial para criar aplicações Solana seguras e eficientes.
O que são EDPs?
Os Endereços Derivados de Programa (EDPs) são endereços especiais que só podem ser derivados por um programa específico. Diferente das contas regulares, os EDPs não têm uma chave privada associada a eles. Isso significa que não podem ser controlados ou gastos diretamente por um usuário, o que proporciona uma segurança adicional para os dados que representam.
Os EDPs são derivados usando o ID do programa e um conjunto de sementes. Isso garante que as mesmas entradas sempre gerarão o mesmo EDP, tornando o processo determinístico.
Derivando um EDP
Para derivar um EDP, você pode utilizar o método Pubkey::find_program_address
fornecido pelo SDK do Solana. A função recebe um array de sementes e um ID de programa e retorna o EDP derivado juntamente com uma semente de "bump" que pode ser usada para assinar transações.
Aqui está como você pode derivar um EDP:
use solana_program::{pubkey::Pubkey, program_pack::Pack};
fn derive_pda(seeds: &[&[u8]], program_id: &Pubkey) -> (Pubkey, u8) {
let (pda, bump_seed) = Pubkey::find_program_address(seeds, program_id);
(pda, bump_seed)
}
Neste exemplo, seeds
é um array de fatias de bytes que serão usadas junto com o ID do programa para derivar o EDP.
Exemplo: Derivando um EDP
Digamos que queremos derivar um EDP para uma conta de usuário em nossa aplicação. Definimos o ID do programa e algumas sementes:
use solana_program::pubkey::Pubkey;
fn main() {
let program_id = Pubkey::new_unique();
let user_seed = b"user_account";
let (user_pda, bump_seed) = derive_pda(&[user_seed], &program_id);
println!("EDP do Usuário: {}", user_pda);
println!("Semente de Bump: {}", bump_seed);
}
Neste exemplo, derivamos um EDP nomeado user_account
usando o ID único de nosso programa.
Usando EDPs na Inicialização de Contas
Os EDPs podem ser usados para armazenar dados para contas em programas Solana. Antes de armazenar dados, você precisa criar e inicializar a conta. Aqui está um exemplo de inicialização de uma conta com base no EDP derivado:
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
info,
};
pub fn initialize_user_account(
program_id: &Pubkey,
accounts: &[AccountInfo],
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let user_account = next_account_info(account_info_iter)?;
// Verifique se a conta do usuário já está inicializada
if user_account.data_is_empty() {
let (user_pda, bump_seed) = derive_pda(&[b"user_account"], program_id);
// Certifique-se de que o EDP corresponde ao endereço da conta
if *user_account.key != user_pda {
return Err(ProgramError::InvalidArgument);
}
// Inicialize os dados da conta (ex: defina um valor padrão)
user_account.data.borrow_mut()[0] = 1; // Exemplo: definir um valor padrão
info!("Conta do usuário inicializada com EDP: {:?}", user_account.key);
}
Ok(())
}
Neste trecho de código, verificamos se a conta do usuário está vazia (não inicializada). Se não estiver inicializada, derivamos o EDP e garantimos que corresponda à chave da conta fornecida antes de inicializá-la.
Acessando Dados a Partir de EDPs
Para acessar dados de um EDP, é importante lembrar que os dados em si são armazenados dentro da conta associada ao EDP. Abaixo está um exemplo de como você pode atualizar e ler dados de um EDP:
pub fn update_user_account(
program_id: &Pubkey,
accounts: &[AccountInfo],
new_value: u8,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let user_account = next_account_info(account_info_iter)?;
// Certifique-se de que o EDP corresponde ao endereço da conta
let (user_pda, _) = derive_pda(&[b"user_account"], program_id);
if *user_account.key != user_pda {
return Err(ProgramError::InvalidArgument);
}
// Atualize os dados da conta
user_account.data.borrow_mut()[0] = new_value;
info!("Conta do usuário atualizada com o novo valor: {}", new_value);
Ok(())
}
pub fn get_user_account_value(
program_id: &Pubkey,
accounts: &[AccountInfo],
) -> ProgramResult<u8> {
let account_info_iter = &mut accounts.iter();
let user_account = next_account_info(account_info_iter)?;
// Certifique-se de que o EDP corresponde ao endereço da conta
let (user_pda, _) = derive_pda(&[b"user_account"], program_id);
if *user_account.key != user_pda {
return Err(ProgramError::InvalidArgument);
}
// Leia os dados da conta
let value = user_account.data.borrow()[0];
Ok(value)
}
Nessas funções, primeiro verificamos se a conta fornecida corresponde ao EDP derivado. Em seguida, lemos e escrevemos dados conforme necessário.
Conclusão
Os Endereços Derivados de Programa (EDPs) fornecem um mecanismo poderoso para a segurança dos dados em programas Solana. Eles garantem que certas contas só podem ser derivadas por programas específicos, eliminando o risco de acesso não autorizado.
Nesta aula, cobrimos como derivar EDPs, inicializar contas e acessar dados armazenados neles. Continue praticando esses conceitos em seus dApps para construir programas Solana seguros e eficientes!