Rust
Pinocchio Quantum Vault

Pinocchio Quantum Vault

9 Graduates

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:

rust
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 })
    }
}

Validasi akun ditangani oleh CPI CreateAccount. Jika akun tidak memenuhi persyaratan (penandatangan, kemampuan diubah, kemampuan dieksekusi), instruksi akan gagal secara otomatis.

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)

Kita mengirimkan bump dari klien daripada menurunkannya on-chain untuk menghemat biaya komputasi.

Begini tampilannya dalam kode:

rust
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 })
    }
}

Di sini juga, parameter yang tidak valid bersifat self-correcting: mengirimkan hash yang salah akan membuat vault tidak berfungsi, mengirimkan bump yang salah akan gagal dalam derivasi PDA.

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.

Bahkan akun kosong harus memenuhi syarat bebas sewa untuk tetap ada di Solana.

Begini tampilannya dalam kode:

rust
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)])
    }
}

Instruksi ini hanya membuat struktur vault. Deposit ditangani secara terpisah melalui transfer lamport sederhana ke akun vault.

Next PagePisahkan Vault
ATAU LANGSUNG KE TANTANGAN
Siap mengambil tantangan?
Daftar Isi
Lihat Sumber
Blueshift © 2025Commit: e573eab