Dokumentasi SolanaMengembangkan Program

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_dalek7edwards21EdwardsBasepointTable6create17h178b3d2411f7f082E
curve25519_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?

Daftar Isi

Edit Halaman