Tài khoản PDA

Tóm tắt

Tạo tài khoản PDA thông qua invoke_signed với các seed của PDA. Chỉ chương trình sở hữu mới có thể ký cho PDA. Ràng buộc init của Anchor tự động hóa việc tạo tài khoản PDA.

Ký PDA thông qua invoke_signed

Khi một chương trình cần ký thay mặt cho PDA trong quá trình CPI, nó sử dụng invoke_signed với các seed của PDA. Runtime xác minh các seed dẫn xuất PDA mong đợi bằng cách sử dụng ID chương trình gọi, đảm bảo chỉ chương trình sở hữu mới có thể ký. Để xem luồng xác minh đầy đủ, hãy xem PDA Signing.

Tạo tài khoản PDA

Dẫn xuất PDA và tạo tài khoản tại PDA là hai thao tác riêng biệt. Bạn phải tạo tài khoản một cách rõ ràng sau khi dẫn xuất địa chỉ.

Để tạo tài khoản tại PDA, chương trình dẫn xuất gọi lệnh create_account của System Program thông qua invoke_signed, truyền các seed của PDA để runtime có thể xác minh quyền của chương trình đối với địa chỉ đó.

Ví dụ dưới đây sử dụng Anchor framework để tạo tài khoản mới với địa chỉ dẫn xuất từ chương trình. Chương trình bao gồm một lệnh initialize duy nhất để tạo tài khoản mới, tài khoản này sẽ lưu trữ địa chỉ người dùngbump seed được sử dụng để dẫn xuất PDA.

Program
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 bump
account_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 PDA
seeds = [b"data", user.key().as_ref()],
// use the canonical bump
bump,
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,
}

Ràng buộc init yêu cầu Anchor gọi System Program để tạo tài khoản mới sử dụng PDA làm địa chỉ. Các seed được sử dụng để tạo PDA là:

  • Chuỗi cố định: "data"
  • Địa chỉ của tài khoản người dùng được cung cấp trong lệnh
  • Bump seed chính tắc

Trong ví dụ này, ràng buộc bump không được gán giá trị, do đó Anchor sẽ sử dụng find_program_address để suy ra PDA và tìm bump.

pda_account
#[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>,

Tệp kiểm thử bên dưới chứa một giao dịch gọi lệnh initialize để tạo một tài khoản mới với địa chỉ suy ra từ chương trình. Tệp này chứa mã để suy ra PDA.

Ví dụ cũng cho thấy cách lấy tài khoản mới sẽ được tạo.

Test
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 program
const [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));
});
});

Nếu bạn gọi lệnh initialize lần nữa với cùng seed địa chỉ user, giao dịch sẽ thất bại. Điều này xảy ra vì một tài khoản đã tồn tại tại địa chỉ đã suy ra.

Is this page helpful?

Mục lục

Chỉnh sửa trang

Quản lý bởi

© 2026 Solana Foundation.
Đã đăng ký bản quyền.
Kết nối