Εκτέλεση προγράμματος

Περίληψη

Τα προγράμματα μεταγλωττίζονται σε sBPF μέσω LLVM και εκτελούνται σε sandboxed VM με προϋπολογισμό 1.4M CU ανά συναλλαγή. Το runtime αποθηκεύει σε cache έως 512 μεταγλωττισμένα προγράμματα, παρέχει syscalls για logging, CPI, κρυπτογραφία και μνήμη, και καθυστερεί νέες αναπτύξεις κατά 1 slot.

Μεταγλώττιση

Η Solana χρησιμοποιεί το LLVM για να μεταγλωττίσει προγράμματα σε ELF binaries που περιέχουν Solana Bytecode Format (sBPF). Το ELF binary αποθηκεύεται on-chain σε έναν εκτελέσιμο λογαριασμό.

Το sBPF είναι η προσαρμοσμένη παραλλαγή της Solana του eBPF bytecode, προσαρμοσμένη για το runtime της Solana. Δεν είναι τυπικό eBPF και έχει τροποποιήσεις ειδικές για τη Solana.

Συγγραφή προγραμμάτων

Τα προγράμματα Solana γράφονται κυρίως σε Rust χρησιμοποιώντας μία από τις δύο προσεγγίσεις:

Μοντέλο εκτέλεσης προγράμματος

Όταν μια συναλλαγή επεξεργάζεται, το runtime εκτελεί κάθε εντολή διαδοχικά μέσω του process_message(). Για κάθε εντολή, το runtime:

  1. Προετοιμάζει το πλαίσιο της εντολής. Καλεί το prepare_next_top_level_instruction() για να αντιστοιχίσει τους δείκτες λογαριασμών της εντολής, να ορίσει τις σημαίες signer και writable, και να διαμορφώσει το TransactionContext.

  2. Ελέγχει τα precompiles. Αν το πρόγραμμα είναι precompile, το runtime καλεί το process_precompile(), το οποίο εξακολουθεί να προσθέτει και να αφαιρεί ένα stack frame (μέσω push() και pop()) αλλά παρακάμπτει το sBPF VM και την αναζήτηση στην cache προγραμμάτων, εκτελώντας native code απευθείας.

  3. Προσθέτει ένα stack frame. (Τα βήματα 3-6 συμβαίνουν μέσα στο InvokeContext::process_instruction() και process_executable_chain(), που καλούνται από το process_message().) Καλεί το push() στο InvokeContext, το οποίο αυξάνει το ύψος της στοίβας εντολών και επιβάλλει τον κανόνα επανεισόδου: ένα πρόγραμμα μπορεί να επανεισέλθει στον εαυτό του μόνο αν ο άμεσος καλών (το πρόγραμμα στην τρέχουσα κορυφή της στοίβας εντολών) είναι το ίδιο πρόγραμμα. Η βαθιά αυτο-αναδρομή (A -> A -> A) επιτρέπεται, υπό την προϋπόθεση των ορίων βάθους στοίβας. Άλλα μοτίβα επανεισόδου (π.χ., το A καλεί το B που καλεί το A) επιστρέφουν InstructionError::ReentrancyNotAllowed.

  4. Επιλύει το πρόγραμμα. Το runtime καλεί το process_executable_chain() το οποίο καθορίζει τον loader. Αν ο κάτοχος του program account είναι ο native loader, το πρόγραμμα είναι builtin και η συνάρτηση entrypoint του αναζητείται απευθείας από το ProgramCacheForTxBatch. Αν ο κάτοχος είναι ένας από τους BPF loaders (bpf_loader_deprecated, bpf_loader, bpf_loader_upgradeable, ή loader_v4), καλείται αντί αυτού το δικό του builtin entrypoint του loader.

  5. Εκτελεί το πρόγραμμα BPF. Για προγράμματα BPF, το loader entrypoint αναζητά το μεταγλωττισμένο εκτελέσιμο από την cache προγραμμάτων. Η συνάρτηση execute() στη συνέχεια:

    • Σειριοποιεί τα δεδομένα του account σε ένα επίπεδο buffer παραμέτρων
    • Δημιουργεί το sBPF VM με stack, heap και περιοχές μνήμης
    • Εκτελεί τον μεταγλωττισμένο κώδικα, καταναλώνοντας compute units κατά την εκτέλεση. Επιστρέφει ComputationalBudgetExceeded αν ξεπεραστεί ο προϋπολογισμός.
    • Αποσειριοποιεί τα δεδομένα του account από το buffer πίσω στην κατάσταση του account
  6. Αφαιρεί το stack frame. Καλεί το pop() το οποίο επαληθεύει ότι η εντολή δεν παραβίασε τους λογιστικούς κανόνες του runtime (τα υπόλοιπα lamport είναι ισοσκελισμένα, τα readonly accounts δεν τροποποιήθηκαν, τα μεγέθη δεδομένων των accounts είναι εντός ορίων).

  7. Συσσωρεύει compute units. Τα compute units που καταναλώθηκαν από την εντολή προστίθενται στο συνολικό ποσό της συναλλαγής μέσω του saturating_add.

Κρυφή μνήμη προγράμματος

Το περιβάλλον εκτέλεσης διατηρεί μια καθολική ProgramCache που αποθηκεύει επαληθευμένα και μεταγλωττισμένα προγράμματα. Είναι ενήμερη για το γράφημα διακλαδώσεων και χειρίζεται τους κανόνες ορατότητας ανάπτυξης, την εξώθηση και την επαναμεταγλώττιση στα όρια των epochs.

Τύποι καταχωρίσεων κρυφής μνήμης

Κάθε πρόγραμμα που βρίσκεται στην κρυφή μνήμη έχει έναν ProgramCacheEntryType που καθορίζει τη συμπεριφορά του κατά την εκτέλεση:

ΤύποςΠεριγραφή
LoadedΕπαληθευμένο και μεταγλωττισμένο πρόγραμμα, έτοιμο για εκτέλεση.
BuiltinΕγγενές πρόγραμμα μεταγλωττισμένο στο δυαδικό αρχείο του validator (System, Stake, Vote, κ.λπ.). Δεν αποθηκεύεται on-chain.
UnloadedΠροηγουμένως επαληθευμένο πρόγραμμα του οποίου το μεταγλωττισμένο εκτελέσιμο αρχείο εξωθήθηκε από τη μνήμη για να ελευθερωθεί χώρος. Εξακολουθεί να παρακολουθεί στατιστικά χρήσης. Μπορεί να επαναφορτωθεί χωρίς επανεπαλήθευση.
FailedVerificationΣημάδι για προγράμματα που δεν πέρασαν τον επαληθευτή sBPF υπό το τρέχον σύνολο χαρακτηριστικών. Μπορεί να γίνει Loaded εάν οι ενεργοποιήσεις χαρακτηριστικών αλλάξουν τους κανόνες επαλήθευσης.
ClosedΣημάδι για προγράμματα που κλείστηκαν ρητά ή δεν αναπτύχθηκαν ποτέ. Χρησιμοποιείται επίσης για λογαριασμούς (όπως λογαριασμοί buffer) που ανήκουν σε έναν φορτωτή αλλά δεν περιέχουν εκτελέσιμο κώδικα.
DelayVisibilityΣυνθετικό σημάδι που επιστρέφεται από το ProgramCacheForTxBatch::find() όταν υπάρχει μια καταχώριση Loaded αλλά δεν είναι ακόμη ενεργή (το effective_slot της είναι στο μέλλον). Δεν αποθηκεύεται ποτέ απευθείας στην κρυφή μνήμη.

Καθυστέρηση ορατότητας

Τα νέα αναπτυγμένα ή αναβαθμισμένα προγράμματα δεν τίθενται σε ισχύ αμέσως. Η σταθερά DELAY_VISIBILITY_SLOT_OFFSET είναι 1, που σημαίνει ότι ένα πρόγραμμα που αναπτύχθηκε στο slot N τίθεται σε ισχύ στο slot N+1. Κατά τη διάρκεια του slot ανάπτυξης, οποιαδήποτε προσπάθεια κλήσης της νέας έκδοσης επιστρέφει DelayVisibility, προκαλώντας το περιβάλλον εκτέλεσης να αναφέρει "Το πρόγραμμα δεν έχει αναπτυχθεί."

Πολιτική εξώθησης

Η προσωρινή μνήμη διατηρεί έως και MAX_LOADED_ENTRY_COUNT (512) μεταγλωττισμένες καταχωρήσεις προγράμματος. Όταν επιτευχθεί το όριο, τα λιγότερο χρησιμοποιούμενα προγράμματα εξωθούνται σε κατάσταση Unloaded. Η χρήση παρακολουθείται από το tx_usage_counter (αυξάνεται κάθε φορά που μια συναλλαγή αναφέρεται στο πρόγραμμα) και το latest_access_slot.

Επαναμεταγλώττιση ορίου epoch

Εάν μια ενεργοποίηση χαρακτηριστικού αλλάξει το ProgramRuntimeEnvironments σε όριο epoch, όλα τα προγράμματα στην προσωρινή μνήμη επαναμεταγλωττίζονται σύμφωνα με το νέο περιβάλλον.

Δεδομένα επιστροφής

Τα προγράμματα μπορούν να ορίσουν δεδομένα επιστροφής μέσω της κλήσης συστήματος sol_set_return_data. Τα δεδομένα αποθηκεύονται σε μια δομή TransactionReturnData επιπέδου συναλλαγής που διατηρεί τα bytes δεδομένων και το program_id του προγράμματος του οποίου η εντολή κάλεσε την κλήση συστήματος. Το μέγιστο μέγεθος είναι 1.024 bytes (MAX_RETURN_DATA).

Is this page helpful?

Διαχειρίζεται από

© 2026 Ίδρυμα Solana.
Με επιφύλαξη παντός δικαιώματος.
Συνδεθείτε