Özet
PDA hesaplarını PDA'nın seed'leriyle invoke_signed aracılığıyla
oluşturun. Yalnızca sahip olan program bir PDA için imza atabilir. Anchor'un
init kısıtlaması PDA hesap oluşturmayı otomatikleştirir.
invoke_signed ile PDA imzalama
Bir program CPI sırasında bir PDA adına imza atması gerektiğinde, PDA'nın
seed'leriyle invoke_signed kullanır. Runtime, seed'lerin çağıran
programın ID'sini kullanarak beklenen PDA'yı türettiğini doğrular ve yalnızca
sahip olan programın imza atabileceğinden emin olur. Tam doğrulama akışı için
PDA imzalama bölümüne bakın.
PDA hesabı oluşturma
Bir PDA türetmek ve PDA'da bir hesap oluşturmak ayrı işlemlerdir. Adresi türettikten sonra hesabı açıkça oluşturmalısınız.
Bir PDA'da hesap oluşturmak için, türeten program System Program'ın
create_account talimatını invoke_signed aracılığıyla
çağırır ve PDA'nın seed'lerini ileterek runtime'ın programın o adres üzerindeki
yetkisini doğrulamasını sağlar.
Aşağıdaki örnek, program türevli bir adresle yeni bir hesap oluşturmak için
Anchor framework kullanır. Program, PDA'yı
türetmek için kullanılan kullanıcı adresini ve
bump seed'ini depolayacak yeni hesabı oluşturmak için tek bir
initialize talimatı içerir.
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,}
init kısıtlaması Anchor'a PDA'yı adres olarak kullanarak yeni
bir hesap oluşturmak için
System Program'ı çağırmasını
söyler. PDA'yı oluşturmak için kullanılan seed'ler şunlardır:
- Sabit dize: "data"
- Talimatta sağlanan kullanıcı hesabının adresi
- Kanonik bump seed
Bu örnekte, bump kısıtlamasına bir değer atanmamıştır, bu nedenle Anchor PDA'yı
türetmek ve bump'ı bulmak için find_program_address kullanacaktır.
#[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>,
Aşağıdaki test dosyası, program türevli bir adresle yeni bir hesap oluşturmak
için initialize talimatını çağıran bir işlem içerir.
Dosya, PDA'yı türetmek için kod içerir.
Örnek ayrıca oluşturulacak yeni hesabın nasıl alınacağını gösterir.
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));});});
Aynı user adres seed'i ile initialize talimatını tekrar çağırırsanız,
işlem başarısız olur. Bu durum, türetilen adreste zaten bir hesap bulunduğu
için gerçekleşir.
Is this page helpful?