Виконання програм

Підсумок

Програми компілюються в sBPF через LLVM і виконуються в ізольованій VM з бюджетом 1.4M CU на транзакцію. Runtime кешує до 512 скомпільованих програм, надає системні виклики для логування, CPI, криптографії та пам'яті, і затримує нові розгортання на 1 slot.

Компіляція

Solana використовує LLVM для компіляції програм у ELF бінарні файли, що містять Solana Bytecode Format (sBPF). ELF бінарний файл зберігається on-chain в виконуваному акаунті.

sBPF — це власний варіант eBPF байткоду від Solana, адаптований для Solana runtime. Це не стандартний eBPF і має специфічні для Solana модифікації.

Написання програм

Програми Solana переважно пишуться на Rust з використанням одного з двох підходів:

Модель виконання програм

Коли транзакція обробляється, runtime виконує кожну інструкцію послідовно через process_message(). Для кожної інструкції runtime:

  1. Підготовлює контекст інструкції. Викликає prepare_next_top_level_instruction() для відображення індексів акаунтів інструкції, встановлення прапорців підписувача та запису, і налаштування TransactionContext.

  2. Перевіряє прекомпіляції. Якщо програма є прекомпіляцією, runtime викликає process_precompile(), який все одно додає та видаляє фрейм стека (через push() та pop()), але обходить sBPF VM та пошук у кеші програм, виконуючи нативний код безпосередньо.

  3. Додає кадр стека. (Кроки 3-6 виконуються всередині InvokeContext::process_instruction() та process_executable_chain(), викликаних з process_message().) Викликає push() на InvokeContext, що збільшує висоту стека інструкцій і застосовує правило реентерабельності: програма може повторно викликати саму себе, лише якщо безпосередній викликач (програма на поточній вершині стека інструкцій) є тією самою програмою. Глибока саморекурсія (A -> A -> A) дозволена з урахуванням обмежень глибини стека. Інші шаблони реентерабельності (наприклад, A викликає B, яка викликає A) повертають InstructionError::ReentrancyNotAllowed.

  4. Визначає програму. Середовище виконання викликає process_executable_chain(), що визначає завантажувач. Якщо власником program account є нативний завантажувач, програма є вбудованою, і її функція точки входу шукається безпосередньо у ProgramCacheForTxBatch. Якщо власником є один із завантажувачів BPF (bpf_loader_deprecated, bpf_loader, bpf_loader_upgradeable або loader_v4), натомість викликається власна вбудована точка входу завантажувача.

  5. Виконує програму BPF. Для програм BPF точка входу завантажувача шукає скомпільований виконуваний файл у кеші програм. Функція execute() потім:

    • Серіалізує дані акаунта в плоский буфер параметрів
    • Створює віртуальну машину sBPF зі стеком, купою та областями пам'яті
    • Запускає скомпільований код, споживаючи обчислювальні одиниці під час виконання. Повертає ComputationalBudgetExceeded, якщо бюджет перевищено.
    • Десеріалізує дані акаунта з буфера назад у стан акаунта
  6. Видаляє кадр стека. Викликає pop(), що перевіряє, чи інструкція не порушила правила обліку середовища виконання (баланси lamport збалансовані, акаунти лише для читання не були змінені, розміри даних акаунтів у межах лімітів).

  7. Накопичує обчислювальні одиниці. Обчислювальні одиниці, спожиті інструкцією, додаються до загальної суми транзакції через saturating_add.

Кеш програм

Середовище виконання підтримує глобальний ProgramCache, який зберігає верифіковані та скомпільовані програми. Він враховує структуру форків і обробляє правила видимості розгортання, витіснення та рекомпіляцію на межах епох.

Типи записів кешу

Кожна закешована програма має ProgramCacheEntryType, який визначає її поведінку під час виконання:

ТипОпис
LoadedВерифікована та скомпільована програма, готова до виконання.
BuiltinНативна програма, скомпільована у бінарний файл валідатора (System, Stake, Vote тощо). Не зберігається в блокчейні.
UnloadedРаніше верифікована програма, скомпільований виконуваний файл якої було витіснено з пам'яті для звільнення місця. Все ще відстежує статистику використання. Може бути перезавантажена без повторної верифікації.
FailedVerificationНадгробок для програм, які не пройшли верифікатор sBPF за поточного набору функцій. Може стати Loaded, якщо активація функцій змінить правила верифікації.
ClosedНадгробок для програм, які були явно закриті або ніколи не розгортались. Також використовується для акаунтів (таких як буферні акаунти), які належать до завантажувача, але не містять виконуваного коду.
DelayVisibilityСинтетичний надгробок, що повертається ProgramCacheForTxBatch::find(), коли запис Loaded існує, але ще не набув чинності (його effective_slot у майбутньому). Ніколи не зберігається безпосередньо в кеші.

Затримка видимості

Нові розгорнуті або оновлені програми не набувають чинності негайно. Константа DELAY_VISIBILITY_SLOT_OFFSET дорівнює 1, що означає, що програма, розгорнута у слоті N, набуває чинності у слоті N+1. Під час слота розгортання будь-яка спроба викликати нову версію повертає DelayVisibility, що змушує середовище виконання повідомити "Програму не розгорнуто".

Політика витіснення

Кеш зберігає до MAX_LOADED_ENTRY_COUNT (512) скомпільованих записів програм. Коли досягається ліміт, найменш використовувані програми витісняються до стану Unloaded. Використання відстежується за допомогою tx_usage_counter (збільшується кожного разу, коли транзакція посилається на програму) та latest_access_slot.

Рекомпіляція на межі epoch

Якщо активація функції змінює ProgramRuntimeEnvironments на межі epoch, усі закешовані програми рекомпілюються для нового середовища.

Повернення даних

Програми можуть встановлювати дані для повернення через системний виклик sol_set_return_data. Дані зберігаються у структурі TransactionReturnData рівня транзакції, яка містить байти даних та program_id програми, чия інструкція викликала системний виклик. Максимальний розмір становить 1024 байти (MAX_RETURN_DATA).

Is this page helpful?

Керується

© 2026 Фонд Solana.
Всі права захищені.
Залишайтеся на зв'язку