Ringkasan
Program dikompilasi ke sBPF melalui LLVM dan dijalankan dalam VM yang terisolasi dengan anggaran 1,4 juta CU per transaksi. Runtime menyimpan cache hingga 512 program yang telah dikompilasi, menyediakan syscall untuk logging, CPI, kripto, dan memori, serta menunda deployment baru sebesar 1 slot.
Kompilasi
Solana menggunakan LLVM untuk mengompilasi program menjadi biner ELF yang berisi Solana Bytecode Format (sBPF). Biner ELF disimpan secara onchain dalam sebuah executable account.
sBPF adalah varian kustom Solana dari bytecode eBPF, yang disesuaikan untuk runtime Solana. Ini bukan eBPF standar dan memiliki modifikasi khusus Solana.
Tulis program
Program Solana terutama ditulis dalam Rust menggunakan salah satu dari tiga pendekatan:
Anchor
Sebuah framework yang menggunakan macro Rust untuk mengurangi boilerplate. Direkomendasikan untuk sebagian besar developer.
Pinocchio
Library Rust ringan dan zero-copy yang dioptimalkan untuk konsumsi compute dan ukuran biner. Menyertakan crate khusus program untuk CPI yang umum digunakan.
Native Rust
Rust langsung tanpa framework. Menawarkan kontrol penuh tetapi memerlukan lebih banyak implementasi manual.
Lihat Cross-Program Invocations untuk konsep dan contoh CPI yang berlaku di semua pendekatan ini.
Model eksekusi program
Saat sebuah transaksi diproses, runtime mengeksekusi setiap instruksi
secara berurutan melalui
process_message().
Untuk setiap instruksi, runtime:
-
Menyiapkan konteks instruksi. Memanggil
prepare_next_top_level_instruction()untuk memetakan indeks akun instruksi, mengatur flag signer dan writable, serta mengonfigurasiTransactionContext. -
Memeriksa precompile. Jika program adalah sebuah precompile, runtime memanggil
process_precompile(), yang tetap melakukan push dan pop stack frame (melaluipush()danpop()) tetapi melewati VM sBPF dan pencarian cache program, mengeksekusi kode native secara langsung. -
Melakukan push stack frame. (Langkah 3-6 terjadi di dalam
InvokeContext::process_instruction()danprocess_executable_chain(), dipanggil dariprocess_message().) Memanggilpush()padaInvokeContext, yang menaikkan tinggi stack instruksi dan memberlakukan aturan reentrancy: sebuah program hanya dapat masuk kembali ke dirinya sendiri jika pemanggil langsung (program di puncak stack instruksi saat ini) adalah program yang sama. Rekursi-diri mendalam (A -> A -> A) diizinkan, tunduk pada batas kedalaman stack. Pola reentrancy lainnya (misalnya, A memanggil B memanggil A) mengembalikanInstructionError::ReentrancyNotAllowed. -
Menyelesaikan program. Runtime memanggil
process_executable_chain()yang menentukan loader. Jika pemilik program account adalah native loader, program adalah builtin dan fungsi entrypointnya dicari langsung dariProgramCacheForTxBatch. Jika pemiliknya adalah salah satu BPF loader (bpf_loader_deprecated,bpf_loader,bpf_loader_upgradeable, atauloader_v4), entrypoint builtin milik loader itu sendiri yang akan dipanggil. -
Mengeksekusi program BPF. Untuk program BPF, loader entrypoint mencari executable yang telah dikompilasi dari cache program. Fungsi
execute()kemudian:- Menserialkan data akun ke dalam buffer parameter flat
- Membuat VM sBPF dengan stack, heap, dan region memori
- Menjalankan kode yang telah dikompilasi, mengonsumsi compute unit selama eksekusi. Mengembalikan
ComputationalBudgetExceededjika anggaran terlampaui. - Mendeserialkan data akun dari buffer kembali ke dalam state akun
-
Melakukan pop stack frame. Memanggil
pop()yang memverifikasi bahwa instruksi tidak melanggar aturan akuntansi runtime (saldo lamport seimbang, akun readonly tidak dimodifikasi, ukuran data akun berada dalam batas). -
Mengakumulasi compute unit. Compute unit yang dikonsumsi oleh instruksi ditambahkan ke total transaksi melalui
saturating_add.
Cache program
Runtime mempertahankan
ProgramCache global
yang menyimpan program yang telah diverifikasi dan dikompilasi. Cache ini mengetahui fork-graph dan menangani
aturan visibilitas deployment, eviction, dan rekompilasi batas epoch.
Tipe entri cache
Setiap program yang di-cache memiliki
ProgramCacheEntryType
yang menentukan perilaku runtimenya:
| Tipe | Deskripsi |
|---|---|
Loaded | Program yang telah diverifikasi dan dikompilasi, siap untuk dieksekusi. |
Builtin | Program native yang dikompilasi ke dalam biner validator (System, Stake, Vote, dll.). Tidak disimpan onchain. |
Unloaded | Program yang sebelumnya telah diverifikasi namun executable yang telah dikompilasi di-evict dari memori untuk membebaskan ruang. Masih melacak statistik penggunaan. Dapat dimuat ulang tanpa verifikasi ulang. |
FailedVerification | Tombstone untuk program yang tidak lolos verifier sBPF di bawah feature set saat ini. Dapat menjadi Loaded jika aktivasi fitur mengubah aturan verifikasi. |
Closed | Tombstone untuk program yang secara eksplisit ditutup atau tidak pernah di-deploy. Juga digunakan untuk akun (seperti buffer account) yang dimiliki oleh loader tetapi tidak berisi kode yang dapat dieksekusi. |
DelayVisibility | Tombstone sintetis yang dikembalikan oleh ProgramCacheForTxBatch::find() ketika entri Loaded ada tetapi belum efektif (effective_slot-nya ada di masa depan). Tidak pernah disimpan langsung di cache. |
Penundaan visibilitas
Program yang baru di-deploy atau diperbarui tidak langsung efektif. Konstanta
DELAY_VISIBILITY_SLOT_OFFSET
bernilai 1, artinya program yang di-deploy pada slot N menjadi efektif pada slot
N+1. Selama slot deployment, setiap upaya untuk memanggil versi baru mengembalikan
DelayVisibility, yang menyebabkan runtime melaporkan "Program is not deployed."
Kebijakan eviction
Cache menampung hingga
MAX_LOADED_ENTRY_COUNT
(512) entri program yang telah dikompilasi. Ketika batas tercapai, program yang paling jarang digunakan
di-evict ke state Unloaded. Penggunaan dilacak oleh
tx_usage_counter
(dinaikkan setiap kali transaksi mereferensikan program) dan
latest_access_slot.
Rekompilasi batas epoch
Jika aktivasi fitur mengubah
ProgramRuntimeEnvironments
pada batas epoch, semua program yang di-cache
dikompilasi ulang
terhadap environment baru.
Data kembalian
Program dapat mengatur data kembalian melalui syscall sol_set_return_data. Data disimpan dalam
struktur TransactionReturnData di tingkat transaksi
yang menyimpan byte data dan program_id dari program yang
instruksinya memanggil syscall. Ukuran maksimum adalah 1.024 byte
(MAX_RETURN_DATA).
Is this page helpful?