Визначення
Syscall (системний виклик) — це механізм, через який програма на Solana звертається до ресурсів середовища виконання. Програми працюють у пісочниці BPF-віртуальної машини і не мають прямого доступу до файлової системи, мережі, годинника чи пам'яті поза своїми межами. Єдиний спосіб отримати ці дані чи виконати дію — викликати syscall.
Простіше кажучи: syscall — це вікно між ізольованою програмою та самим блокчейном Solana. Через нього програма читає стан мережі, записує логи, викликає інші програми (CPI) і працює з пам'яттю.
Як працює
Коли програма на Rust компілюється у BPF-байткод, стандартні бібліотечні функції (наприклад, введення-виведення, системні виклики ОС) замінюються на спеціальні інструкції, які розпізнає BPF-віртуальна машина Solana. Під час виконання ці інструкції перехоплюються рантаймом і обробляються як syscall.
Процес виглядає так:
- Програма викликає функцію з префіксом sol_ (наприклад, sol_log_).
- BPF-VM розпізнає цей виклик і передає керування рантайму Solana.
- Рантайм перевіряє права, виділяє ресурси та виконує запитану дію.
- Результат повертається в програму.
Кожен 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 для роботи з системними змінними.