Ringkasan
Buat akun PDA melalui invoke_signed dengan seed PDA. Hanya program
pemilik yang dapat menandatangani untuk PDA. Constraint init Anchor
mengotomatiskan pembuatan akun PDA.
Penandatanganan PDA melalui invoke_signed
Ketika program perlu menandatangani atas nama PDA selama CPI, program tersebut
menggunakan invoke_signed dengan seed PDA. Runtime memverifikasi seed
menurunkan PDA yang diharapkan menggunakan ID program pemanggil, memastikan
hanya program pemilik yang dapat menandatangani. Untuk alur verifikasi lengkap,
lihat Penandatanganan PDA.
Membuat akun PDA
Menurunkan PDA dan membuat akun di PDA adalah operasi terpisah. Anda harus secara eksplisit membuat akun setelah menurunkan alamat.
Untuk membuat akun di PDA, program penurunan memanggil instruksi
create_account System Program melalui invoke_signed,
meneruskan seed PDA sehingga runtime dapat memverifikasi otoritas program atas
alamat tersebut.
Contoh di bawah ini menggunakan
framework Anchor untuk membuat akun baru
dengan alamat yang diturunkan program. Program ini mencakup satu instruksi
initialize untuk membuat akun baru, yang akan menyimpan
alamat pengguna dan bump seed yang
digunakan untuk menurunkan 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,}
Constraint init memberi tahu Anchor untuk
memanggil System Program
untuk membuat akun baru menggunakan PDA sebagai alamat. Seed
yang digunakan untuk membuat PDA adalah:
- String tetap: "data"
- Alamat akun pengguna yang disediakan dalam instruksi
- Canonical bump seed
Dalam contoh ini, constraint bump tidak diberi nilai, sehingga Anchor akan
menggunakan find_program_address untuk menurunkan PDA dan menemukan 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>,
File pengujian di bawah ini berisi transaksi yang memanggil instruksi
initialize untuk membuat akun baru dengan
program-derived address. File ini berisi kode untuk
menurunkan PDA.
Contoh ini juga menunjukkan cara mengambil akun baru yang akan dibuat.
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));});});
Jika Anda memanggil instruksi initialize lagi dengan seed alamat user yang
sama, transaksi akan gagal. Ini terjadi karena akun sudah ada di alamat yang
diturunkan.
Is this page helpful?