Ringkasan
Program dikompilasi ke sBPF melalui LLVM dan berjalan dalam VM sandbox dengan anggaran 1,4 juta CU per transaksi. Runtime menyimpan cache hingga 512 program yang dikompilasi, menyediakan syscall untuk logging, CPI, kripto, dan memori, serta menunda deployment baru sebanyak 1 slot.
Kompilasi
Solana menggunakan LLVM untuk mengompilasi program ke dalam binari ELF yang berisi Solana Bytecode Format (sBPF). Binari ELF disimpan on-chain dalam akun yang dapat dieksekusi.
sBPF adalah varian khusus Solana dari bytecode eBPF, yang disesuaikan untuk runtime Solana. Ini bukan eBPF standar dan memiliki modifikasi khusus Solana.
Menulis program
Program Solana terutama ditulis dalam Rust menggunakan salah satu dari dua pendekatan:
Anchor
Framework yang menggunakan makro Rust untuk mengurangi boilerplate. Direkomendasikan untuk sebagian besar developer.
Native Rust
Rust langsung tanpa framework. Menawarkan kontrol penuh tetapi memerlukan lebih banyak implementasi manual.
Model eksekusi program
Ketika 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, dan mengonfigurasiTransactionContext. -
Memeriksa precompile. Jika program adalah precompile, runtime memanggil
process_precompile(), yang masih melakukan push dan pop stack frame (melaluipush()danpop()) tetapi melewati sBPF VM dan pencarian cache program, mengeksekusi kode native secara langsung. -
Mendorong stack frame. (Langkah 3-6 terjadi di dalam
InvokeContext::process_instruction()danprocess_executable_chain(), dipanggil dariprocess_message().) Memanggilpush()padaInvokeContext, yang menambah tinggi stack instruksi dan menerapkan aturan reentrancy: sebuah program hanya dapat masuk kembali ke dirinya sendiri jika pemanggil langsung (program di posisi teratas stack instruksi saat ini) adalah program yang sama. Rekursi diri yang dalam (A -> A -> A) diperbolehkan, tergantung 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 tersebut adalah builtin dan fungsi entrypoint-nya dicari langsung dariProgramCacheForTxBatch. Jika pemiliknya adalah salah satu BPF loader (bpf_loader_deprecated,bpf_loader,bpf_loader_upgradeable, atauloader_v4), entrypoint builtin loader itu sendiri yang dipanggil. -
Mengeksekusi program BPF. Untuk program BPF, entrypoint loader mencari executable yang telah dikompilasi dari cache program.
execute()kemudian:- Menserialisasi data account ke dalam buffer parameter datar
- Membuat VM sBPF dengan stack, heap, dan region memori
- Menjalankan kode yang telah dikompilasi, mengonsumsi unit komputasi selama
eksekusi. Mengembalikan
ComputationalBudgetExceededjika anggaran terlampaui. - Mendeserialisasi data account dari buffer kembali ke state account
-
Mengeluarkan stack frame. Memanggil
pop()yang memverifikasi bahwa instruksi tidak melanggar aturan akuntansi runtime (saldo lamport seimbang, account readonly tidak dimodifikasi, ukuran data account berada dalam batas). -
Mengakumulasi unit komputasi. Unit komputasi yang dikonsumsi oleh instruksi ditambahkan ke total transaksi melalui
saturating_add.
Cache program
Runtime memelihara
ProgramCache
global yang menyimpan program yang telah diverifikasi dan dikompilasi. Cache ini
menyadari fork-graph dan menangani aturan visibilitas deployment, eviction, dan
kompilasi ulang pada batas epoch.
Jenis entri cache
Setiap program yang di-cache memiliki
ProgramCacheEntryType
yang menentukan perilaku runtime-nya:
| Jenis | Deskripsi |
|---|---|
Loaded | Program yang telah diverifikasi dan dikompilasi, siap untuk dieksekusi. |
Builtin | Program native yang dikompilasi ke dalam binary validator (System, Stake, Vote, dll.). Tidak disimpan on-chain. |
Unloaded | Program yang sebelumnya telah diverifikasi namun executable yang dikompilasi telah dievict dari memori untuk mengosongkan 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 akun buffer) yang termasuk dalam 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 di masa depan). Tidak pernah disimpan langsung di cache. |
Penundaan visibilitas
Program yang baru di-deploy atau di-upgrade tidak langsung efektif. Konstanta
DELAY_VISIBILITY_SLOT_OFFSET
adalah 1, yang berarti program yang di-deploy di slot N menjadi efektif di
slot N+1. Selama slot deployment, setiap upaya untuk memanggil versi baru
mengembalikan DelayVisibility, menyebabkan runtime melaporkan "Program is
not deployed."
Kebijakan eviksi
Cache menyimpan hingga
MAX_LOADED_ENTRY_COUNT
(512) entri program yang dikompilasi. Ketika batas tercapai, program yang paling
jarang digunakan akan dieviksi ke status Unloaded. Penggunaan dilacak oleh
tx_usage_counter
(ditambahkan 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 akan
dikompilasi ulang
terhadap lingkungan yang baru.
Data pengembalian
Program dapat mengatur data pengembalian melalui syscall sol_set_return_data.
Data disimpan dalam
TransactionReturnData
struct 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?