Samenvatting
Programma's compileren naar sBPF via LLVM en draaien in een gesandboxte VM met een 1,4M CU budget per transactie. De runtime cachet tot 512 gecompileerde programma's, biedt syscalls voor logging, CPI, crypto en geheugen, en vertraagt nieuwe deployments met 1 slot.
Compilatie
Solana gebruikt LLVM om programma's te compileren naar ELF binaries die Solana Bytecode Format (sBPF) bevatten. De ELF binary wordt on-chain opgeslagen in een uitvoerbaar account.
sBPF is Solana's aangepaste variant van eBPF bytecode, op maat gemaakt voor de Solana runtime. Het is geen standaard eBPF en heeft Solana-specifieke aanpassingen.
Programma's schrijven
Solana programma's worden voornamelijk geschreven in Rust met een van twee benaderingen:
Anchor
Een framework dat Rust macro's gebruikt om boilerplate te verminderen. Aanbevolen voor de meeste ontwikkelaars.
Native Rust
Direct Rust zonder frameworks. Biedt volledige controle maar vereist meer handmatige implementatie.
Programma-uitvoeringsmodel
Wanneer een transactie wordt verwerkt, voert de runtime elke instructie
sequentieel uit via
process_message().
Voor elke instructie doet de runtime het volgende:
-
Bereidt de instructiecontext voor. Roept
prepare_next_top_level_instruction()aan om de account-indices van de instructie te mappen, signer- en writable-vlaggen in te stellen, en deTransactionContextte configureren. -
Controleert precompiles. Als het programma een precompile is, roept de runtime
process_precompile()aan, wat nog steeds een stack frame pusht en popt (viapush()enpop()) maar de sBPF VM en programma-cache lookup omzeilt en native code direct uitvoert. -
Pusht een stack frame. (Stappen 3-6 gebeuren binnen
InvokeContext::process_instruction()enprocess_executable_chain(), aangeroepen vanuitprocess_message().) Roeptpush()aan opInvokeContext, wat de hoogte van de instructiestack verhoogt en de reentrancy-regel afdwingt: een programma mag zichzelf alleen opnieuw betreden als de directe aanroeper (het programma bovenaan de huidige instructiestack) hetzelfde programma is. Diepe zelfrecursie (A -> A -> A) is toegestaan, onder voorbehoud van stackdieptelimieten. Andere reentrancy-patronen (bijv. A roept B aan die A aanroept) retournerenInstructionError::ReentrancyNotAllowed. -
Lost het programma op. De runtime roept
process_executable_chain()aan, wat de loader bepaalt. Als de eigenaar van het program account de native loader is, is het programma een builtin en wordt de entrypoint-functie direct opgezocht in deProgramCacheForTxBatch. Als de eigenaar een van de BPF-loaders is (bpf_loader_deprecated,bpf_loader,bpf_loader_upgradeable, ofloader_v4), wordt in plaats daarvan het builtin entrypoint van de loader aangeroepen. -
Voert het BPF-programma uit. Voor BPF-programma's zoekt het loader entrypoint het gecompileerde uitvoerbare bestand op uit de programmacache. De
execute()functie doet vervolgens:- Serialiseert accountgegevens naar een platte parameterbuffer
- Creëert de sBPF VM met stack-, heap- en geheugenregio's
- Voert de gecompileerde code uit en verbruikt compute units tijdens de
uitvoering. Retourneert
ComputationalBudgetExceededals het budget wordt overschreden. - Deserialiseert accountgegevens van de buffer terug naar de accountstatus
-
Popt het stack frame. Roept
pop()aan, wat verifieert dat de instructie de boekhoudregels van de runtime niet heeft geschonden (lamport-saldi zijn in balans, alleen-lezen accounts zijn niet gewijzigd, accountgegevensgroottes vallen binnen de limieten). -
Accumuleert compute units. De compute units die door de instructie zijn verbruikt, worden toegevoegd aan het transactietotaal via
saturating_add.
Programma-cache
De runtime onderhoudt een globale
ProgramCache
die geverifieerde en gecompileerde programma's opslaat. Deze is
fork-graph-bewust en handelt zichtbaarheidsregels voor deployment, verwijdering
en hercompilatie bij epoch-grenzen af.
Cache-invoertypen
Elk gecachet programma heeft een
ProgramCacheEntryType
die het runtime-gedrag bepaalt:
| Type | Beschrijving |
|---|---|
Loaded | Geverifieerd en gecompileerd programma, klaar voor uitvoering. |
Builtin | Native programma gecompileerd in de validator-binary (System, Stake, Vote, etc.). Niet on-chain opgeslagen. |
Unloaded | Eerder geverifieerd programma waarvan het gecompileerde uitvoerbare bestand uit het geheugen is verwijderd om ruimte vrij te maken. Houdt nog steeds gebruiksstatistieken bij. Kan opnieuw worden geladen zonder herverificatie. |
FailedVerification | Tombstone voor programma's die de sBPF-verifier niet hebben doorstaan onder de huidige feature set. Kan Loaded worden als feature-activeringen de verificatieregels wijzigen. |
Closed | Tombstone voor programma's die expliciet zijn gesloten of nooit zijn gedeployed. Ook gebruikt voor accounts (zoals buffer-accounts) die tot een loader behoren maar geen uitvoerbare code bevatten. |
DelayVisibility | Synthetische tombstone geretourneerd door ProgramCacheForTxBatch::find() wanneer een Loaded-invoer bestaat maar nog niet effectief is (de effective_slot ligt in de toekomst). Wordt nooit direct in de cache opgeslagen. |
Zichtbaarheidsvertraging
Nieuw gedeployde of geüpgrade programma's zijn niet onmiddellijk effectief. De
DELAY_VISIBILITY_SLOT_OFFSET
constante is 1, wat betekent dat een programma dat in slot N is gedeployed
effectief wordt in slot N+1. Tijdens de deployment-slot retourneert elke poging
om de nieuwe versie aan te roepen DelayVisibility, waardoor de runtime
meldt "Programma is niet gedeployed."
Verwijderingsbeleid
De cache bevat maximaal
MAX_LOADED_ENTRY_COUNT
(512) gecompileerde programma-items. Wanneer de limiet wordt bereikt, worden de
minst gebruikte programma's verwijderd naar de Unloaded status. Gebruik
wordt bijgehouden door
tx_usage_counter
(verhoogd telkens wanneer een transactie naar het programma verwijst) en
latest_access_slot.
Hercompilatie bij epoch-grens
Als een functie-activatie de
ProgramRuntimeEnvironments
bij een epoch-grens wijzigt, worden alle gecachte programma's
gehercompileerd
tegen de nieuwe omgeving.
Retourgegevens
Programma's kunnen retourgegevens instellen via de sol_set_return_data
syscall. De gegevens worden opgeslagen in een transactieniveau
TransactionReturnData
struct die de databytes en de program_id bevat van het programma waarvan de
instructie de syscall aanriep. De maximale grootte is 1.024 bytes
(MAX_RETURN_DATA).
Is this page helpful?