FAQ
Ajukan pertanyaan Anda di StackExchange.
Berkeley Packet Filter (BPF)
Program onchain Solana dikompilasi melalui infrastruktur kompiler LLVM ke dalam Executable and Linkable Format (ELF) yang berisi variasi dari Berkeley Packet Filter (BPF) bytecode.
Karena Solana menggunakan infrastruktur kompiler LLVM, program dapat ditulis dalam bahasa pemrograman apa pun yang dapat menargetkan backend BPF dari LLVM.
BPF menyediakan set instruksi yang efisien yang dapat dijalankan dalam mesin virtual yang diinterpretasi atau sebagai instruksi native yang dikompilasi just-in-time yang efisien.
Peta memori
Peta memori alamat virtual yang digunakan oleh program SBF Solana bersifat tetap dan disusun sebagai berikut
- Kode program dimulai pada 0x100000000
- Data stack dimulai pada 0x200000000
- Data heap dimulai pada 0x300000000
- Parameter input program dimulai pada 0x400000000
Alamat virtual di atas adalah alamat awal, tetapi program diberikan akses ke
subset dari peta memori. Program akan panik jika mencoba membaca atau menulis ke
alamat virtual yang tidak diberikan aksesnya, dan kesalahan AccessViolation
akan dikembalikan yang berisi alamat dan ukuran pelanggaran yang dicoba.
InvalidAccountData
Kesalahan program ini dapat terjadi karena banyak alasan. Biasanya, ini disebabkan oleh pengiriman akun ke program yang tidak diharapkan oleh program, baik dalam posisi yang salah dalam instruksi atau akun yang tidak kompatibel dengan instruksi yang sedang dijalankan.
Implementasi program juga dapat menyebabkan kesalahan ini ketika melakukan instruksi lintas program dan lupa menyediakan akun untuk program yang Anda panggil.
InvalidInstructionData
Error program ini dapat terjadi saat mencoba melakukan deserialisasi instruksi,
periksa bahwa struktur yang dimasukkan cocok persis dengan instruksi. Mungkin
ada beberapa padding di antara field. Jika program mengimplementasikan trait
Rust Pack
maka coba melakukan packing dan unpacking tipe instruksi T
untuk
menentukan encoding yang tepat yang diharapkan program.
MissingRequiredSignature
Beberapa instruksi mengharuskan akun menjadi penandatangan; error ini dikembalikan jika akun diharapkan ditandatangani tetapi tidak.
Implementasi program juga dapat menyebabkan error ini ketika melakukan
cross-program invocation yang memerlukan alamat program yang
ditandatangani, tetapi seed penandatangan yang diteruskan ke invoke_signed
tidak cocok dengan seed penandatangan yang digunakan untuk membuat alamat
program create_program_address
.
Stack
SBF menggunakan frame stack alih-alih pointer stack variabel. Setiap frame stack berukuran 4KB.
Jika program melanggar ukuran frame stack tersebut, compiler akan melaporkan pelanggaran sebagai peringatan.
Contohnya:
Error: Function _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E Stack offset of -30728 exceeded max offset of -4096 by 26632 bytes, please minimize large stack variables
Pesan tersebut mengidentifikasi simbol mana yang melebihi frame stack-nya, tetapi namanya mungkin termangled.
Untuk demangle simbol Rust gunakan rustfilt.
Peringatan di atas berasal dari program Rust, jadi nama simbol yang sudah di-demangle adalah:
rustfilt _ZN16curve25519_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082Ecurve25519_dalek::edwards::EdwardsBasepointTable::create
Alasan peringatan dilaporkan daripada error adalah karena beberapa crate
dependensi mungkin menyertakan fungsionalitas yang melanggar batasan frame stack
bahkan jika program tidak menggunakan fungsionalitas tersebut. Jika program
melanggar ukuran stack saat runtime, error AccessViolation
akan dilaporkan.
Frame stack SBF menempati rentang alamat virtual yang dimulai dari
0x200000000
.
Ukuran heap
Program memiliki akses ke runtime heap melalui API Rust alloc
. Untuk
memfasilitasi alokasi yang cepat, heap bump sederhana sebesar 32KB digunakan.
Heap tidak mendukung free
atau realloc
.
Secara internal, program memiliki akses ke region memori 32KB yang dimulai dari alamat virtual 0x300000000 dan dapat mengimplementasikan heap kustom berdasarkan kebutuhan spesifik program.
Program Rust mengimplementasikan heap secara langsung dengan mendefinisikan
global_allocator
kustom
Loader
Program di-deploy dan dieksekusi oleh runtime loader, saat ini ada dua loader yang didukung BPF Loader dan BPF loader deprecated
Loader mungkin mendukung antarmuka biner aplikasi yang berbeda sehingga
pengembang harus menulis program mereka untuk dan men-deploy-nya ke loader yang
sama. Jika program yang ditulis untuk satu loader di-deploy ke loader yang
berbeda, hasilnya biasanya adalah error AccessViolation
karena ketidakcocokan
deserialisasi parameter input program.
Untuk semua tujuan praktis, program harus selalu ditulis untuk menargetkan BPF loader terbaru dan loader terbaru adalah default untuk antarmuka command-line dan API javascript.
Deployment
Deployment program SBF adalah proses mengunggah objek bersama BPF ke dalam data
akun program dan menandai akun sebagai executable. Klien memecah objek bersama
SBF menjadi bagian-bagian yang lebih kecil dan mengirimkannya sebagai data
instruksi dari instruksi
Write
ke loader di mana loader menulis data tersebut ke dalam data akun program.
Setelah semua bagian diterima, klien mengirimkan instruksi
Finalize
ke loader, loader kemudian memvalidasi bahwa data SBF valid dan menandai akun
program sebagai executable. Setelah akun program ditandai executable,
transaksi selanjutnya dapat mengeluarkan instruksi untuk program tersebut untuk
diproses.
Ketika sebuah instruksi diarahkan ke program SBF yang dapat dieksekusi, loader mengkonfigurasi lingkungan eksekusi program, menserialkan parameter input program, memanggil entrypoint program, dan melaporkan kesalahan yang ditemui.
Untuk informasi lebih lanjut, lihat men-deploy program.
Serialisasi Parameter Input
Loader SBF menserialkan parameter input program menjadi array byte yang kemudian diteruskan ke entrypoint program, di mana program bertanggung jawab untuk mendeserialkannya on-chain. Salah satu perubahan antara loader lama yang tidak digunakan lagi dan loader saat ini adalah parameter input diserialkan dengan cara yang menghasilkan berbagai parameter jatuh pada offset yang selaras dalam array byte yang selaras. Ini memungkinkan implementasi deserialisasi untuk mereferensikan langsung array byte dan menyediakan pointer yang selaras ke program.
Loader terbaru menserialkan parameter input program sebagai berikut (semua pengkodean adalah little endian):
- 8 byte angka unsigned jumlah akun
- Untuk setiap akun
- 1 byte menunjukkan apakah ini adalah akun duplikat, jika bukan duplikat maka nilainya adalah 0xff, jika tidak nilainya adalah indeks akun yang diduplikasi.
- Jika duplikat: 7 byte padding
- Jika bukan duplikat:
- 1 byte boolean, true jika akun adalah penandatangan
- 1 byte boolean, true jika akun dapat ditulis
- 1 byte boolean, true jika akun dapat dieksekusi
- 4 byte padding
- 32 byte kunci publik akun
- 32 byte kunci publik pemilik akun
- 8 byte angka unsigned lamport yang dimiliki oleh akun
- 8 byte angka unsigned jumlah byte data akun
- x byte data akun
- 10k byte padding, digunakan untuk realloc
- padding yang cukup untuk menyelaraskan offset ke 8 byte.
- 8 byte rent epoch
- 8 byte angka unsigned jumlah instruction data
- x byte instruction data
- 32 byte program id
Is this page helpful?