Визначення

Syscall (системний виклик) — це механізм, через який програма на Solana звертається до ресурсів середовища виконання. Програми працюють у пісочниці BPF-віртуальної машини і не мають прямого доступу до файлової системи, мережі, годинника чи пам'яті поза своїми межами. Єдиний спосіб отримати ці дані чи виконати дію — викликати syscall.

Простіше кажучи: syscall — це вікно між ізольованою програмою та самим блокчейном Solana. Через нього програма читає стан мережі, записує логи, викликає інші програми (CPI) і працює з пам'яттю.

Як працює

Коли програма на Rust компілюється у BPF-байткод, стандартні бібліотечні функції (наприклад, введення-виведення, системні виклики ОС) замінюються на спеціальні інструкції, які розпізнає BPF-віртуальна машина Solana. Під час виконання ці інструкції перехоплюються рантаймом і обробляються як syscall.

Процес виглядає так:

  1. Програма викликає функцію з префіксом sol_ (наприклад, sol_log_).
  2. BPF-VM розпізнає цей виклик і передає керування рантайму Solana.
  3. Рантайм перевіряє права, виділяє ресурси та виконує запитану дію.
  4. Результат повертається в програму.

Кожен syscall споживає обчислювальні одиниці (compute units). Рантайм також накладає ліміти на розмір переданих даних і кількість викликів у межах однієї транзакції, щоб запобігти DoS-атакам.

Серед найуживаніших syscall на Solana:

  • sol_log_ — запис повідомлення у лог транзакції;
  • sol_invoke_signed — виклик іншої програми (CPI);
  • sol_get_clock_sysvar та аналогічні — читання системних змінних (sysvar);
  • sol_memcpy_, sol_memset_ — робота з пам'яттю;
  • sol_create_program_address — обчислення адреси PDA.

Приклад

Нижче наведено виклик syscall для запису в лог транзакції в програмі на Rust:

sol_log_("Ініціалізація контракту завершена");

Під час компіляції цей виклик перетворюється на BPF-інструкцію, яку рантайм обробляє як системний виклик. Результат — рядок з'являється в логах транзакції й доступний через RPC-метод getTransaction.

Інший приклад — читання поточного слоту через sysvar:

let clock = Clock::get()?;
msg!("Поточний слот: {}", clock.slot);

Під капотом макрос Clock::get() з бібліотеки Anchor викликає syscall sol_get_clock_sysvar, який завантажує дані системної змінної Clock у пам'ять програми.

Типова помилка

Найпоширеніша помилка — використання стандартних функцій Rust, які під капотом роблять системні виклики ОС, але не існують у BPF-середовищі Solana. Наприклад, прямий виклик println! замість msg! або sol_log_ призведе до помилки компіляції, оскільки BPF-ціль не підтримує стандартне введення-виведення.

Інша помилка — ігнорування обмежень на кількість і глибину syscall у межах транзакції. Занадто багато вкладених викликів sol_invoke_signed (глибоке CPI) може вичерпати ліміт обчислювальних одиниць, і транзакція впаде з помилкою ComputationalBudgetExceeded.

Пов'язані матеріали

Внутрішні переходи

  • BPF Loader — компонент, який завантажує BPF-програми та забезпечує виконання їхніх syscall під час транзакції.
  • Log (журнал транзакцій) — куди потрапляють результати syscall sol_log_ і макросу msg!.

Додаткові ресурси

  • Офіційна документація Solana: розділ Runtime → Syscalls — повний перелік доступних syscall із описом параметрів і лімітів.
  • Репозиторій solana-sdk на GitHub: файл sysvar/src/ — реалізація обгорток над syscall для роботи з системними змінними.

Джерела