Buka Vault
Instruksi open membuat Program Derived Address (PDA) vault tempat lamport akan disimpan dengan aman. PDA ini menggunakan kunci publik yang di-hash sebagai seed-nya, memastikan hanya pemegang kunci asli yang dapat menarik dana nantinya.
PDA menyediakan cara yang aman untuk menyimpan dana karena:
Hanya program Anda yang dapat mengontrol akun (tidak ada kunci privat yang ada)
Alamat vault diturunkan secara deterministik dari hash pengguna
Penarikan hanya dapat terjadi melalui logika program Anda
Required Accounts
Instruksi ini memerlukan akun-akun berikut:
payer: Membayar untuk pembuatan vault (harus penandatangan dan dapat diubah)vault: PDA yang sedang diinisialisasi (harus dapat diubah)system_program: Diperlukan untuk pembuatan akun (harus dapat dieksekusi)
Dalam kode, ini terlihat seperti:
pub struct OpenVaultAccounts<'a> {
pub payer: &'a AccountInfo,
pub vault: &'a AccountInfo,
}
impl<'a> TryFrom<&'a [AccountInfo]> for OpenVaultAccounts<'a> {
type Error = ProgramError;
fn try_from(accounts: &'a [AccountInfo]) -> Result<Self, Self::Error> {
let [payer, vault, _system_program] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
Ok(Self { payer, vault })
}
}Instruction Data
Dua bagian data diperlukan:
hash: Hash SHA-256 dari kunci publik pasangan kunci winternitz pengguna ([u8; 32])bump: Bump derivasi PDA yang dikirim dari klien (u8)
Begini tampilannya dalam kode:
pub struct OpenVaultInstructionData {
pub hash: [u8; 32],
pub bump: [u8; 1],
}
impl<'a> TryFrom<&'a [u8]> for OpenVaultInstructionData {
type Error = ProgramError;
fn try_from(data: &'a [u8]) -> Result<Self, Self::Error> {
if data.len() != core::mem::size_of::<OpenVaultInstructionData>() {
return Err(ProgramError::InvalidInstructionData);
}
let hash = data[0..32].try_into().map_err(|_| ProgramError::InvalidInstructionData)?;
let bump = data[32..33].try_into().map_err(|_| ProgramError::InvalidInstructionData)?;
Ok(Self { hash, bump })
}
}Instruction Logic
Instruksi ini membuat PDA kosong yang ditetapkan ke program kita. Meskipun akun tidak menyimpan data, kepemilikan program memastikan penarikan hanya dapat terjadi melalui logika yang kita kontrol.
Begini tampilannya dalam kode:
pub struct OpenVault<'a> {
pub accounts: OpenVaultAccounts<'a>,
pub instruction_data: OpenVaultInstructionData,
}
impl<'a> TryFrom<(&'a [u8], &'a [AccountInfo])> for OpenVault<'a> {
type Error = ProgramError;
fn try_from((data, accounts): (&'a [u8], &'a [AccountInfo])) -> Result<Self, Self::Error> {
let instruction_data = OpenVaultInstructionData::try_from(data)?;
let accounts = OpenVaultAccounts::try_from(accounts)?;
Ok(Self { accounts, instruction_data })
}
}
impl<'a> OpenVault<'a> {
pub const DISCRIMINATOR: &'a u8 = &0;
pub fn process(&self) -> ProgramResult {
let lamports = Rent::get()?.minimum_balance(0);
let seeds = [Seed::from(&self.instruction_data.hash), Seed::from(&self.instruction_data.bump)];
// Create our vault
CreateAccount {
from: self.accounts.payer,
to: self.accounts.vault,
lamports,
space: 0,
owner: &crate::ID,
}
.invoke_signed(&[Signer::from(&seeds)])
}
}