Özet
Programlar LLVM aracılığıyla sBPF'ye derlenir ve işlem başına 1,4M CU bütçesi olan korumalı bir VM'de çalışır. Runtime, 512 adede kadar derlenmiş programı önbelleğe alır, loglama, CPI, kripto ve bellek için syscall'lar sağlar ve yeni dağıtımları 1 slot geciktirir.
Derleme
Solana, programları Solana Bytecode Format (sBPF) içeren ELF binary'lerine derlemek için LLVM kullanır. ELF binary, zincir üzerinde yürütülebilir bir hesapta saklanır.
sBPF, Solana runtime'ı için özelleştirilmiş eBPF bytecode'unun Solana'ya özgü varyantıdır. Standart eBPF değildir ve Solana'ya özgü değişiklikler içerir.
Program yazma
Solana programları öncelikli olarak iki yaklaşımdan biri kullanılarak Rust ile yazılır:
Anchor
Boilerplate'i azaltmak için Rust makrolarını kullanan bir framework. Çoğu geliştirici için önerilir.
Native Rust
Framework olmadan doğrudan Rust. Tam kontrol sunar ancak daha fazla manuel uygulama gerektirir.
Program yürütme modeli
Bir işlem işlendiğinde, runtime her talimatı sırayla
process_message()
aracılığıyla yürütür. Her talimat için runtime:
-
Talimat bağlamını hazırlar. Talimatın hesap indekslerini eşlemek, imzalayan ve yazılabilir bayraklarını ayarlamak ve
TransactionContext'i yapılandırmak içinprepare_next_top_level_instruction()'i çağırır. -
Precompile'ları kontrol eder. Program bir precompile ise, runtime
process_precompile()'i çağırır, bu hala bir stack frame'i push ve pop eder (push()vepop()aracılığıyla) ancak sBPF VM ve program önbelleği aramasını atlayarak native kodu doğrudan yürütür. -
Bir yığın çerçevesi iter. (3-6. adımlar
InvokeContext::process_instruction()veprocess_executable_chain()içinde gerçekleşir,process_message()tarafından çağrılır.)push()fonksiyonunuInvokeContextüzerinde çağırır, bu da komut yığını yüksekliğini artırır ve yeniden giriş kuralını uygular: bir program yalnızca doğrudan çağıran (komut yığınının mevcut tepesindeki program) aynı programsa kendisine yeniden girebilir. Derin öz-özyineleme (A -> A -> A) yığın derinliği sınırlarına tabi olarak izin verilir. Diğer yeniden giriş kalıpları (örneğin, A, B'yi çağırır, B, A'yı çağırır)InstructionError::ReentrancyNotAlloweddöndürür. -
Programı çözümler. Çalışma zamanı
process_executable_chain()fonksiyonunu çağırır ve yükleyiciyi belirler. Program hesabının sahibi native loader ise, program bir builtin'dir ve giriş noktası fonksiyonu doğrudanProgramCacheForTxBatchiçinden aranır. Sahip BPF yükleyicilerinden biri ise (bpf_loader_deprecated,bpf_loader,bpf_loader_upgradeableveyaloader_v4), bunun yerine yükleyicinin kendi builtin giriş noktası çağrılır. -
BPF programını çalıştırır. BPF programları için, loader entrypoint derlenmiş çalıştırılabilir dosyayı program önbelleğinden arar.
execute()fonksiyonu ardından:- Hesap verilerini düz bir parametre arabelleğine serileştirir
- Yığın, heap ve bellek bölgeleriyle sBPF VM'ini oluşturur
- Derlenmiş kodu çalıştırır, yürütme sırasında işlem birimlerini tüketir.
Bütçe aşılırsa
ComputationalBudgetExceededdöndürür. - Hesap verilerini arabellekten tekrar hesap durumuna deserileştirir
-
Yığın çerçevesini çıkarır.
pop()fonksiyonunu çağırır ve komutun çalışma zamanının muhasebe kurallarını ihlal etmediğini doğrular (lamport bakiyeleri dengelidir, salt okunur hesaplar değiştirilmemiştir, hesap veri boyutları sınırlar dahilindedir). -
İşlem birimlerini biriktirir. Komut tarafından tüketilen işlem birimleri,
saturating_addaracılığıyla işlem toplamına eklenir.
Program önbelleği
Çalışma zamanı, doğrulanmış ve derlenmiş programları saklayan global bir
ProgramCache
tutmaktadır. Fork-graph farkındalığına sahiptir ve dağıtım görünürlük
kurallarını, tahliye işlemlerini ve epoch sınırı yeniden derlemelerini yönetir.
Önbellek giriş türleri
Önbelleğe alınmış her programın, çalışma zamanı davranışını belirleyen bir
ProgramCacheEntryType
bulunmaktadır:
| Tür | Açıklama |
|---|---|
Loaded | Doğrulanmış ve derlenmiş program, yürütmeye hazır. |
Builtin | Validator binary'sine derlenmiş native program (System, Stake, Vote, vb.). Zincir üzerinde saklanmaz. |
Unloaded | Daha önce doğrulanmış ancak derlenmiş çalıştırılabilir dosyası alan boşaltmak için bellekten tahliye edilmiş program. Hala kullanım istatistiklerini takip eder. Yeniden doğrulama olmadan yeniden yüklenebilir. |
FailedVerification | Mevcut özellik seti altında sBPF doğrulayıcısını geçemeyen programlar için mezar taşı. Özellik aktivasyonları doğrulama kurallarını değiştirirse Loaded olabilir. |
Closed | Açıkça kapatılmış veya hiç dağıtılmamış programlar için mezar taşı. Ayrıca bir loader'a ait olan ancak çalıştırılabilir kod içermeyen hesaplar (buffer hesapları gibi) için kullanılır. |
DelayVisibility | ProgramCacheForTxBatch::find() tarafından bir Loaded girişi mevcut olduğunda ancak henüz etkin olmadığında (effective_slot gelecekte olduğunda) döndürülen sentetik mezar taşı. Önbellekte asla doğrudan saklanmaz. |
Görünürlük gecikmesi
Yeni dağıtılan veya yükseltilen programlar hemen etkin olmaz.
DELAY_VISIBILITY_SLOT_OFFSET
sabiti 1'dir, yani N slotunda dağıtılan bir program N+1 slotunda etkin hale
gelir. Dağıtım slotu sırasında, yeni sürümü çağırma girişimi
DelayVisibility döndürür ve çalışma zamanının "Program dağıtılmamış"
bildirmesine neden olur.
Çıkarma politikası
Önbellek en fazla
MAX_LOADED_ENTRY_COUNT
(512) derlenmiş program girişi tutar. Limite ulaşıldığında, en az kullanılan
programlar Unloaded durumuna çıkarılır. Kullanım,
tx_usage_counter
(bir işlem programa her referans verdiğinde artırılır) ve
latest_access_slot
tarafından izlenir.
Epoch sınırında yeniden derleme
Bir özellik aktivasyonu epoch sınırında
ProgramRuntimeEnvironments
değiştirirse, önbellekteki tüm programlar yeni ortama karşı
yeniden derlenir.
Dönüş verisi
Programlar sol_set_return_data syscall'u aracılığıyla dönüş verisi
ayarlayabilir. Veri, işlem düzeyinde bir
TransactionReturnData
struct'ında saklanır ve bu struct veri baytlarını ile syscall'u çağıran
talimatın programının program_id değerini tutar. Maksimum boyut 1.024 bayttır
(MAX_RETURN_DATA).
Is this page helpful?