Riepilogo
Crea account PDA tramite invoke_signed con i seed del PDA. Solo il
programma proprietario può firmare per un PDA. Il constraint init di
Anchor automatizza la creazione di account PDA.
Firma PDA tramite invoke_signed
Quando un programma deve firmare per conto di un PDA durante un CPI, utilizza
invoke_signed con i seed del PDA. Il runtime verifica che i seed derivino
il PDA atteso usando l'ID del programma chiamante, garantendo che solo il
programma proprietario possa firmare. Per il flusso di verifica completo, vedi
firma PDA.
Crea un account PDA
Derivare un PDA e creare un account a un PDA sono operazioni separate. Devi creare esplicitamente l'account dopo aver derivato l'indirizzo.
Per creare un account a un PDA, il programma derivante invoca l'istruzione
create_account del System Program tramite
invoke_signed, passando i seed del PDA in modo che il
runtime possa verificare l'autorità del programma su quell'indirizzo.
L'esempio seguente utilizza il
framework Anchor per creare un nuovo account
con un indirizzo derivato dal programma. Il programma include una singola
istruzione initialize per creare il nuovo account, che
memorizzerà l'indirizzo utente e il
bump seed utilizzati per derivare il PDA.
use anchor_lang::prelude::*;declare_id!("75GJVCJNhaukaa2vCCqhreY31gaphv7XTScBChmr1ueR");#[program]pub mod pda_account {use super::*;pub fn initialize(ctx: Context<Initialize>) -> Result<()> {let account_data = &mut ctx.accounts.pda_account;// store the address of the `user`account_data.user = *ctx.accounts.user.key;// store the canonical bumpaccount_data.bump = ctx.bumps.pda_account;Ok(())}}#[derive(Accounts)]pub struct Initialize<'info> {#[account(mut)]pub user: Signer<'info>,#[account(init,// define the seeds to derive the PDAseeds = [b"data", user.key().as_ref()],// use the canonical bumpbump,payer = user,space = 8 + DataAccount::INIT_SPACE // 8 bytes for Anchor account discriminator)]pub pda_account: Account<'info, DataAccount>,pub system_program: Program<'info, System>,}#[account]#[derive(InitSpace)]pub struct DataAccount {pub user: Pubkey,pub bump: u8,}
Il constraint init indica ad Anchor di
invocare il System Program
per creare un nuovo account usando il PDA come indirizzo. I
seed utilizzati per creare il PDA sono:
- La stringa fissa: "data"
- L'indirizzo dell'account utente fornito nell'istruzione
- Il bump seed canonico
In questo esempio, il vincolo bump non ha un valore assegnato, quindi Anchor
userà find_program_address per derivare il PDA e trovare il bump.
#[account(init,seeds = [b"data", user.key().as_ref()],bump,payer = user,space = 8 + DataAccount::INIT_SPACE // 8 bytes for Anchor account discriminator)]pub pda_account: Account<'info, DataAccount>,
Il file di test qui sotto contiene una transazione che invoca l'istruzione
initialize per creare un nuovo account con un indirizzo
derivato dal programma. Il file contiene il codice per
derivare il PDA.
L'esempio mostra anche come recuperare il nuovo account che verrà creato.
import * as anchor from "@coral-xyz/anchor";import { Program } from "@coral-xyz/anchor";import { PdaAccount } from "../target/types/pda_account";import { PublicKey } from "@solana/web3.js";describe("pda-account", () => {const provider = anchor.AnchorProvider.env();anchor.setProvider(provider);const program = anchor.workspace.PdaAccount as Program<PdaAccount>;const user = provider.wallet as anchor.Wallet;// Derive the PDA address using the seeds specified on the programconst [PDA] = PublicKey.findProgramAddressSync([Buffer.from("data"), user.publicKey.toBuffer()],program.programId);it("Is initialized!", async () => {const transactionSignature = await program.methods.initialize().accounts({user: user.publicKey}).rpc();console.log("Transaction Signature:", transactionSignature);});it("Fetch Account", async () => {const pdaAccount = await program.account.dataAccount.fetch(PDA);console.log(JSON.stringify(pdaAccount, null, 2));});});
Se invochi nuovamente l'istruzione initialize con lo stesso seed di
indirizzo user, la transazione fallirà. Questo accade perché esiste già un
account all'indirizzo derivato.
Is this page helpful?