Runtime akun

Ringkasan

Sebelum eksekusi, runtime memuat akun, memvalidasi pembayar biaya, memeriksa pembebasan sewa, dan menserialisasi data akun ke dalam tata letak memori yang dapat diakses oleh program.

Halaman ini membahas internal runtime. Sebagian besar developer tidak memerlukan informasi ini untuk membangun program. Lihat Struktur akun untuk tampilan yang menghadap ke developer.

Pemuatan akun

Sebelum transaksi dieksekusi, runtime memuat semua akun yang direferensikan melalui load_transaction_accounts(). Proses ini melakukan beberapa validasi:

  1. Validasi pembayar biaya: Pembayar biaya (akun pertama) harus ada, berupa akun sistem atau akun nonce, dan memiliki lamport yang cukup untuk menutupi biaya (validate_fee_payer()). Setelah membayar biaya, akun harus tetap bebas sewa atau menjadi tepat 0 lamport. Akun tidak boleh berakhir di antara 0 dan minimum bebas sewa. Akun nonce harus selalu mempertahankan lamport yang cukup untuk tetap bebas sewa. Jika pembayar bukan akun sistem maupun akun nonce, transaksi gagal dengan TransactionError::InvalidAccountForFee.

  2. Batas ukuran data yang dimuat: Total ukuran semua akun yang dimuat (termasuk TRANSACTION_ACCOUNT_BASE_SIZE sebesar 64 byte per akun) tidak boleh melebihi MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES (64 MiB). Melebihi batas ini menghasilkan TransactionError::MaxLoadedAccountsDataSizeExceeded.

  3. Validasi akun program: Setiap program yang dipanggil oleh instruksi harus ada dan dimiliki oleh loader yang valid: salah satu dari PROGRAM_OWNERS (BPF Loader Upgradeable, BPF Loader, BPF Loader Deprecated, Loader V4) atau native loader. Jika akun program tidak ada, transaksi gagal dengan TransactionError::ProgramAccountNotFound. Jika ada tetapi memiliki owner yang tidak valid, transaksi gagal dengan TransactionError::InvalidProgramForExecution.

  4. Akun yang tidak ada: Akun yang tidak ada di on-chain dimuat sebagai akun default (0 lamport, data kosong, dimiliki oleh system program) dengan rent_epoch diatur ke u64::MAX.

Format serialisasi BPF

Ketika sebuah program dipanggil, runtime menserialisasi akun ke dalam buffer memori yang bersebelahan dan meneruskannya ke BPF VM. Format serialisasi (untuk format aligned standar yang digunakan oleh semua loader kecuali loader-v1 yang usang) didefinisikan dalam serialize_parameters_aligned().

Buffer dimulai dengan u64 (8 byte, little-endian) yang berisi jumlah akun. Kemudian, untuk setiap akun dalam instruksi, buffer berisi:

OffsetUkuranFieldTipe
01duplicate markeru8 (0xFF = unik, index = duplikat dari akun tersebut)
11is_signeru8 (0 atau 1)
21is_writableu8 (0 atau 1)
31executableu8 (0 atau 1)
44original_data_len (reserved, selalu 0)[0u8; 4]
832keyPubkey
4032ownerPubkey
728lamportsu64 (little-endian)
808data_lenu64 (little-endian)
88data_lendata[u8]
88 + data_len10240 + paddingrealloc space + alignmentDiisi nol hingga MAX_PERMITTED_DATA_INCREASE (10 KiB) + padding untuk align ke BPF_ALIGN_OF_U128 (8 byte)
...8rent_epochu64 (little-endian)

Setelah semua akun, buffer menambahkan:

UkuranField
8instruction_data_len (u64, little-endian)
instruction_data_leninstruction_data
32program_id (Pubkey)

Untuk akun duplikat, hanya 1 byte (penanda duplikat dengan indeks dari akun asli) ditambah 7 byte padding yang ditulis.

Deduplikasi akun

Ketika kunci publik akun yang sama muncul beberapa kali dalam array accounts instruksi, runtime melakukan deduplikasi terhadap mereka. Setiap entri dalam daftar akun instruksi mendapatkan struct InstructionAccount sendiri, tetapi entri yang merujuk ke akun tingkat transaksi yang sama menunjuk ke data yang sama.

Metode is_instruction_account_duplicate menentukan apakah indeks akun instruksi tertentu adalah kemunculan pertama atau duplikat dengan mencari indeks akun tingkat transaksi dan menemukan indeks tingkat instruksi pertama yang memetakan ke sana:

  • Jika indeks akun instruksi saat ini sama dengan indeks yang dipetakan pertama, maka bukan duplikat (mengembalikan None).
  • Jika tidak, mengembalikan Some(first_index), di mana first_index adalah indeks dari kemunculan pertama.

Karena semua referensi ke akun yang sama berbagi AccountSharedData yang sama, modifikasi melalui referensi apa pun langsung terlihat melalui semua referensi lainnya. Namun, hanya satu pinjaman mutable yang dapat dipegang pada satu waktu. Mencoba meminjam akun yang sama secara mutable melalui dua indeks akun instruksi yang berbeda secara bersamaan mengembalikan InstructionError::AccountBorrowFailed. Program harus melepaskan satu pinjaman sebelum mengambil yang lain pada akun yang sama.

Setelah program dieksekusi, runtime melakukan deserialisasi buffer kembali (deserialize_parameters_aligned()) dan menerapkan perubahan apa pun ke lamports, data (termasuk perubahan panjang hingga MAX_PERMITTED_DATA_INCREASE), dan owner.

Is this page helpful?

Daftar Isi

Edit Halaman

Dikelola oleh

© 2026 Yayasan Solana.
Semua hak dilindungi.
Terhubung