Özet
Programlar, LLVM aracılığıyla sBPF'e derlenir ve işlem başına 1,4 milyon CU bütçesiyle korumalı bir VM'de çalışır. Çalışma zamanı, derlenmiş 512 programa kadar önbelleğe alır, loglama, CPI, kripto ve bellek için sistem çağrıları sağlar ve yeni dağıtımları 1 slot geciktirir.
Derleme
Solana, programları Solana Bytecode Format (sBPF) içeren ELF binaries dosyalarına derlemek için LLVM kullanır. ELF ikili dosyası, zincir üzerinde yürütülebilir bir hesapta depolanır.
sBPF, Solana'nın eBPF bayt kodunun özel bir varyantıdır ve Solana çalışma zamanına göre özelleştirilmiştir. Standart eBPF değildir ve Solana'ya özgü değişiklikler içerir.
Program yazma
Solana programları öncelikli olarak üç yaklaşımdan biri kullanılarak Rust ile yazılır:
Anchor
Ortak kod tekrarını azaltmak için Rust makrolarını kullanan bir çerçeve. Çoğu geliştirici için önerilir.
Pinocchio
Hesaplama tüketimi ve ikili boyut için optimize edilmiş, hafif, sıfır kopyalı bir Rust kütüphanesi. Yaygın CPI'lar için programa özgü crate'ler içerir.
Native Rust
Çerçevesiz doğrudan Rust. Tam kontrol sağlar ancak daha fazla manuel uygulama gerektirir.
Bu yaklaşımlarda geçerli olan CPI kavramları ve örnekleri için Cross-Program Invocations bölümüne bakın.
Program yürütme modeli
Bir işlem işlendiğinde, çalışma zamanı her talimatı
process_message()
aracılığıyla sırayla yürütür.
Her talimat için çalışma zamanı:
-
Talimat bağlamını hazırlar. Talimatın hesap indekslerini eşlemek, imzalayan ve yazılabilir bayrakları ayarlamak ve
TransactionContext'i yapılandırmak içinprepare_next_top_level_instruction()işlevini çağırır. -
Ön derlemeleri kontrol eder. Program bir precompile ise, çalışma zamanı
process_precompile()işlevini çağırır; bu işlev yine bir yığın çerçevesi iter ve çeker (push()vepop()aracılığıyla) ancak sBPF VM ve program önbelleği aramasını atlayarak yerel kodu doğrudan yürütür. -
Bir yığın çerçevesi iter. (3-6. adımlar,
process_message()'den çağrılanInvokeContext::process_instruction()veprocess_executable_chain()içinde gerçekleşir.) Talimat yığını yüksekliğini artıran ve yeniden giriş kuralını zorunlu kılanInvokeContextüzerindepush()çağrısı yapar: bir program, yalnızca anlık çağıran (talimat yığınının mevcut tepesindeki program) aynı program ise kendisini yeniden çağırabilir. Derin öz-özyineleme (A -> A -> A) yığın derinlik sınırlarına tabi olarak izin verilir. Diğer yeniden giriş desenleri (örneğin, A, B'yi çağırır, B, A'yı çağırır)InstructionError::ReentrancyNotAlloweddöndürür. -
Programı çözer. Çalışma zamanı, yükleyiciyi belirleyen
process_executable_chain()işlevini çağırır. program account'ın sahibi native loader ise, program bir yerleşik programdır ve giriş noktası işlevi doğrudanProgramCacheForTxBatch'ten aranır. Sahibin BPF yükleyicilerinden biri olması durumunda (bpf_loader_deprecated,bpf_loader,bpf_loader_upgradeableveyaloader_v4), yükleyicinin kendi yerleşik giriş noktası çağrılır. -
BPF programını yürütür. BPF programları için, loader entrypoint derlenmiş yürütülebilir dosyayı program önbelleğinden arar. Ardından
execute()işlevi:- Hesap verilerini düz bir parametre tamponuna serileştirir
- Yığın, heap ve bellek bölgeleriyle sBPF VM'i oluşturur
- Derlenmiş kodu çalıştırır ve yürütme sırasında hesaplama birimleri tüketir. Bütçe aşılırsa
ComputationalBudgetExceededdöndürür. - Hesap verilerini tampondan hesap durumuna geri seri dışı bırakır
-
Yığın çerçevesini çıkarır.
pop()çağrısı yapar; bu, talimatın ç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). -
Hesaplama birimlerini biriktirir. Talimat tarafından tüketilen hesaplama birimleri,
saturating_addaracılığıyla işlem toplamına eklenir.
Program önbelleği
Çalışma zamanı, doğrulanmış ve derlenmiş programları depolayan global bir
ProgramCache
tutar. Çatal grafiğini algılar ve dağıtım görünürlük kurallarını, tahliyeyi
ve epoch sınırı yeniden derlemesini yönetir.
Önbellek giriş türleri
Önbelleğe alınan her programın, çalışma zamanı davranışını belirleyen bir
ProgramCacheEntryType
değeri vardır:
| Tür | Açıklama |
|---|---|
Loaded | Doğrulanmış ve derlenmiş program, yürütmeye hazır. |
Builtin | validator ikili dosyasına derlenmiş yerel program (System, Stake, Vote vb.). Zincir üzerinde depolanmaz. |
Unloaded | Daha önce doğrulanmış ancak derlenmiş yürütülebilir dosyası alan açmak için bellekten tahliye edilmiş program. Kullanım istatistiklerini izlemeye devam eder. Yeniden doğrulama yapılmadan yeniden yüklenebilir. |
FailedVerification | Mevcut özellik kümesi altında sBPF doğrulayıcısından geçemeyen programlar için mezar taşı. Özellik etkinleştirmeleri doğrulama kurallarını değiştirirse Loaded olabilir. |
Closed | Açıkça kapatılan veya hiç dağıtılmamış programlar için mezar taşı. Bir yükleyiciye ait olan ancak yürütülebilir kod içermeyen hesaplar (tampon hesapları gibi) için de kullanılır. |
DelayVisibility | Bir Loaded girdisi mevcut olduğu ancak henüz etkin olmadığı durumlarda (yani effective_slot değeri gelecekte olduğunda) ProgramCacheForTxBatch::find() tarafından döndürülen yapay mezar taşı. Önbellekte 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 slot N'de dağıtılan bir program slot N+1'de etkin hale gelir. Dağıtım slot'u süresince, yeni sürümü çağırma girişimi
DelayVisibility döndürür ve çalışma zamanı "Program is not deployed." hatasını raporlar.
Tahliye politikası
Önbellek en fazla
MAX_LOADED_ENTRY_COUNT
(512) derlenmiş program girdisi tutar. Sınıra ulaşıldığında, en az kullanılan
programlar Unloaded durumuna tahliye edilir. Kullanım,
tx_usage_counter
(her işlem programı referans aldığında artırılır) ve
latest_access_slot
aracılığıyla izlenir.
Epoch sınırı yeniden derlemesi
Bir özellik etkinleştirmesi, epoch sınırında
ProgramRuntimeEnvironments
değerini değiştirirse, önbelleğe alınan tüm programlar yeni ortama karşı
yeniden derlenir.
Dönüş verisi
Programlar, sol_set_return_data sistem çağrısı aracılığıyla dönüş verisi ayarlayabilir. Veriler, veri baytlarını ve sistem çağrısını çağıran talimatın program_id'sini tutan bir işlem düzeyindeki
TransactionReturnData
yapısında depolanır. Maksimum boyut 1.024 bayttır
(MAX_RETURN_DATA).
Is this page helpful?