Assembly
Assembly Timeout

Assembly Timeout

9 Graduates

Assembly Timeout

Таймаут збірки

Завдання з таймауту збірки

У цьому розділі ми використаємо sBPF Assembly для створення інструкції перевірки на основі часу, яка забезпечує дотримання крайніх термінів висоти слоту.

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

Кілька властивостей роблять перевірки таймауту ідеальними для асемблера:

  • Єдиний, обмежений варіант використання

  • Ефективне використання системних змінних

  • Не потрібна складна перевірка облікових записів

  • Лише покращує безпеку транзакцій

Якщо ви не знайомі з програмуванням на асемблері, пройдіть вступний курс з асемблера

Дизайн програми

Наша програма реалізує важливу часову операцію: перевірку того, що поточна висота слоту блокчейну не перевищила заздалегідь визначений крайній термін. Цей патерн є важливим для часово-чутливих операцій DeFi — від запобігання застарілим спробам арбітражу до забезпечення дотримання термінів аукціонів.

Програма очікує:

  • 8-байтову максимальну висоту слоту в даних інструкції.

  • Доступ до системної змінної Solana Clock через sol_get_clock_sysvar.

  • Повертає успіх, якщо поточний слот ≤ максимального слоту, інакше — помилку.

Зміщення пам'яті

Програми sBPF отримують дані облікових записів як суміжні області пам'яті. Ці константи визначають байтові зміщення в цій пам'яті.

Оскільки наша програма не приймає жодних облікових записів, ми можемо обчислити, де буде розташовано MAX_SLOT_HEIGHT (передається як дані інструкції). Ми також зберігатимемо дані системної змінної Clock у стеку, з цієї причини CURRENT_SLOT_HEIGHT буде від'ємним.

Ці константи визначають нашу структуру пам'яті:

sbpf
.equ NUM_ACCOUNTS, 0x0000
.equ MAX_SLOT_HEIGHT, 0x0010
.equ CURRENT_SLOT_HEIGHT, -0x0028
  • NUM_ACCOUNTS (0x0000): Вказує на кількість облікових записів у заголовку даних інструкції для перевірки

  • MAX_SLOT_HEIGHT (0x0010): Визначає місцезнаходження 8-байтової висоти слоту крайнього терміну в корисному навантаженні даних інструкції

  • CURRENT_SLOT_HEIGHT (-0x0028): Зміщення стеку, де буде зберігатися поле слоту системної змінної Clock. Оскільки слот є першим полем у структурі Clock, це зміщення вказує безпосередньо на нього

На відміну від мов високого рівня, які абстрагують розташування пам'яті, асемблер вимагає точного знання, де знаходиться кожен фрагмент даних.

Entrypoint and Initial Validation

sbpf
.globl entrypoint
entrypoint:
  ldxdw r0, [r1+NUM_ACCOUNTS]       // Veto if any accounts are included
  ldxdw r2, [r1+MAX_SLOT_HEIGHT]    // Store target slot height

Кожна програма sBPF починається з глобального символу .entrypoint. Середовище виконання Solana надає дані облікового запису та інструкції через регістр r1.

Інструкція ldxdw завантажує (ldx) 8-байтове (подвійне слово, dx) значення з пам'яті в регістр. Ось що відбувається:

  • ldxdw r0, [r1+NUM_ACCOUNTS]: завантажує кількість облікових записів у r0. Оскільки r0 є регістром, який VM читає при виході, будь-яке ненульове значення автоматично призводить до невдачі програми (саме те, що нам потрібно, якщо передаються облікові записи).

  • ldxdw r2, [r1+MAX_SLOT_HEIGHT]: вказує на максимально дозволену висоту слоту, яку ми передали в даних інструкції. Це 64-бітне значення потрапляє в r2.

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

The Clock Sysvar

sbpf
mov64 r1, r10
add64 r1, CURRENT_SLOT_HEIGHT
call sol_get_clock_sysvar
ldxdw r1, [r1+0x0000]

Системний виклик sol_get_clock_sysvar записує поточні дані Clock в r1.

Оскільки структура Clock має розмір 40 байтів (занадто велика для регістрів, які містять лише по 8 байтів), ми використовуємо стек для швидкого зберігання без виділення пам'яті з автоматичним очищенням.

Оскільки r10 доступний лише для читання, для роботи зі стеком нам потрібно скопіювати його адресу пам'яті в регістр: mov64 r1, r10

Потім ми додаємо CURRENT_SLOT_HEIGHT (-0x0028) до r1. Оскільки ця константа від'ємна, це фактично віднімання: r1 = r10 - 40 bytes, що виділяє 40 байтів на стеку.

Після виклику функції sol_get_clock_sysvar, r1 містить адресу пам'яті, куди були записані дані Clock, а не саме значення слоту. З цієї причини ми продовжуємо завантажувати фактичне значення слоту за допомогою ldxdw r1, [r1+0x0000].

Логіка часового порівняння

sbpf
jle r1, r2, end    // If current slot <= max slot, success
lddw r0, 1         // Otherwise, set error code

Основна логіка тайм-ауту використовує один умовний перехід:

  • Часова валідація: jle (перехід, якщо менше або дорівнює) порівнює поточний слот (r1) з нашим дедлайном (r2). Якщо ми в межах часового вікна, перехід до exit

  • Обробка тайм-ауту: Якщо дедлайн минув, виконання продовжується завантаженням (lddw) коду помилки 1 у регістр повернення r0

Висновок

Ця компактна програма виконує часову валідацію з мінімальним споживанням обчислювальних ресурсів.

Компромісом є розуміння інтерфейсів системних викликів, управління стеком та бінарної структури sysvar Clock. Але для критично важливих за продуктивністю часових валідацій, асемблер забезпечує неперевершену ефективність.

Готові прийняти завдання?
Blueshift © 2025Commit: e573eab