ملخص
إنشاء حسابات PDA عبر invoke_signed مع بذور PDA. فقط البرنامج المالك
يمكنه التوقيع نيابة عن PDA. قيد init في Anchor يقوم بأتمتة إنشاء حساب
PDA.
التوقيع بواسطة PDA عبر invoke_signed
عندما يحتاج برنامج إلى التوقيع نيابة عن PDA أثناء CPI، فإنه يستخدم
invoke_signed مع بذور PDA. يتحقق وقت التشغيل من أن البذور تشتق PDA المتوقع
باستخدام معرف البرنامج المستدعي، مما يضمن أن البرنامج المالك فقط يمكنه
التوقيع. للاطلاع على تدفق التحقق الكامل، راجع
توقيع PDA.
إنشاء حساب PDA
اشتقاق PDA وإنشاء حساب عند PDA هما عمليتان منفصلتان. يجب عليك إنشاء الحساب بشكل صريح بعد اشتقاق العنوان.
لإنشاء حساب عند PDA، يستدعي البرنامج المشتق تعليمة create_account الخاصة
ببرنامج النظام عبر invoke_signed، مع تمرير بذور PDA حتى
يتمكن وقت التشغيل من التحقق من صلاحية البرنامج على ذلك العنوان.
يستخدم المثال أدناه إطار عمل Anchor لإنشاء
حساب جديد بعنوان مشتق من البرنامج. يتضمن البرنامج تعليمة
initialize واحدة لإنشاء الحساب الجديد، الذي سيخزن
عنوان المستخدم و بذرة bump المستخدمة
لاشتقاق 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,}
قيد init يخبر Anchor
باستدعاء برنامج النظام
لإنشاء حساب جديد باستخدام PDA كعنوان. البذور المستخدمة لإنشاء
PDA هي:
- السلسلة النصية الثابتة: "data"
- عنوان حساب المستخدم المقدم في التعليمات
- bump seed القياسي
في هذا المثال، لم يتم تعيين قيمة لقيد bump، لذا سيستخدم Anchor
find_program_address لاشتقاق PDA والعثور على 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>,
يحتوي ملف الاختبار أدناه على معاملة تستدعي تعليمات
initialize لإنشاء حساب جديد بعنوان مشتق من البرنامج.
يحتوي الملف على كود لاشتقاق PDA.
يوضح المثال أيضًا كيفية جلب الحساب الجديد الذي سيتم إنشاؤه.
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));});});
إذا قمت باستدعاء تعليمات initialize مرة أخرى بنفس seed عنوان user، ستفشل
المعاملة. يحدث هذا لأن حسابًا موجود بالفعل على العنوان المشتق.
Is this page helpful?