Версіоновані Транзакції Solana: Розширені Можливості та Власні Інструкції
Детальний посібник зі створення та виконання версіонованих транзакцій на Solana
На Solana користувачі взаємодіють з мережею, надсилаючи транзакції. Транзакції містять одну або кілька інструкцій, які визначають операції для обробки. Нещодавно на Solana була впроваджена нова модель транзакцій – версіоновані транзакції (Versioned Transactions), що розширює функціональність порівняно зі старим форматом (legacy transactions). Цей формат дозволяє, зокрема, використовувати Address Lookup Tables (ALTs), що підвищує ефективність та дозволяє включати більше адрес у одну транзакцію.
Ключові Аспекти Версіонованих Транзакцій
- Версіоновані транзакції представляють собою новий формат транзакцій на Solana, що надає розширені можливості порівняно з legacy транзакціями.
- Основна перевага версіонованих транзакцій полягає у можливості використання Address Lookup Tables (ALTs), які дозволяють ефективніше керувати адресами рахунків у транзакціях.
- Розробники, які працюють з клієнтською стороною, повинні оновлювати свій код для підтримки версіонованих транзакцій, хоча зміни до ончейн-програм зазвичай не потрібні.
Розуміння Транзакцій на Solana
Транзакція на Solana — це атомарна операція, яка може містити одну або кілька інструкцій. Кожна інструкція представляє собою окрему дію, яку необхідно виконати програмою на блокчейні. Атомарність означає, що або всі інструкції в транзакції виконуються успішно, або жодна з них не виконується, і транзакція повністю відхиляється.
Структура транзакції на Solana включає:
- Підписи (Signatures): Масив підписів, які підтверджують дозвіл на виконання транзакції від відповідних рахунків.
- Повідомлення (Message): Містить інформацію про інструкції, які потрібно виконати, та рахунки, задіяні в транзакції.
Інструкції Транзакції
Кожна інструкція в транзакції складається з трьох основних компонентів:
- ID програми (Program ID): Адреса програми, яку викликає інструкція.
- Задіяні рахунки (Accounts): Масив адрес рахунків, з якими взаємодіє інструкція (читання або запис).
- Дані інструкції (Instruction Data): Буфер байтів, що містить специфічні для програми дані, необхідні для виконання інструкції.
Явно вказуючи рахунки, з якими інструкція читає або записує, Solana може паралельно виконувати транзакції, які не взаємодіють з тими самими рахунками, що значно збільшує пропускну здатність мережі.
Еволюція Транзакцій: Від Legacy до Версіонованих
До появи версіонованих транзакцій на Solana використовувався єдиний формат, який зараз називається "legacy". Legacy транзакції мають фіксований розмір і обмежену кількість рахунків, які можуть бути включені безпосередньо в повідомлення транзакції. Зі зростанням складності додатків на Solana виникла потреба в більш гнучкому та ефективному способі обробки транзакцій, особливо для тих, що взаємодіють з великою кількістю рахунків.
Версіоновані транзакції (Версія 0, на даний момент) були впроваджені для вирішення цих обмежень. Вони дозволяють використовувати Address Lookup Tables (ALTs), що кардинально змінює спосіб управління адресами рахунків у транзакціях.
Address Lookup Tables (ALTs)
ALTs — це ончейн-таблиці, які зберігають колекції адрес рахунків. Замість того, щоб включати повні 32-байтові адреси всіх задіяних рахунків безпосередньо в повідомлення транзакції (як це робилося в legacy транзакціях), версіоновані транзакції можуть посилатися на рахунки в ALT за допомогою однобайтового індексу. Це ефективно стискає 32-байтову адресу до 1 байта, дозволяючи включати значно більше рахунків у одну транзакцію. Одна ALT може зберігати до 256 адрес.
Використання ALTs звільняє місце в транзакції, яке раніше займали адреси рахунків, дозволяючи включати більше інструкцій або даних в рамках того ж ліміту розміру транзакції. Це особливо корисно для складних операцій, таких як обміни на децентралізованих біржах (DEX), які можуть вимагати взаємодії з багатьма рахунками (пулами ліквідності, рахунками користувачів тощо).
Переваги Версіонованих Транзакцій
-
Збільшення кількості рахунків: Можливість включати значно більше рахунків за допомогою ALTs.
-
Зменшення розміру транзакції: Ефективне використання простору за рахунок посилань на ALTs.
-
Підвищення гнучкості: Краща підтримка складних багатоступеневих операцій.
-
Потенціал для майбутніх функцій: Версіонований формат полегшує впровадження нових функцій у майбутньому.
Сумісність та Перехід
На даний момент Solana підтримує обидва типи транзакцій: legacy та versioned (v0). Існуючі ончейн-програми зазвичай не потребують змін для підтримки версіонованих транзакцій. Однак, клієнтські додатки (фронтенд, гаманці, SDK) мають бути оновлені, щоб коректно обробляти та створювати версіоновані транзакції. Якщо клієнт не вказує підтримку версіонованих транзакцій (наприклад, через параметр maxSupportedTransactionVersion в RPC-запитах), він може отримати помилку при обробці транзакцій версії 0.
Формування Власної Версіонованої Транзакції та Інструкцій
Створення версіонованої транзакції на Solana подібне до створення legacy транзакції, але з деякими ключовими відмінностями, особливо при використанні ALTs. Процес зазвичай включає наступні кроки:
1. Визначення Інструкцій
Кожна дія, яку ви хочете виконати на блокчейні, повинна бути представлена у вигляді інструкції. Для власних операцій, що викликають кастомні програми, вам потрібно визначити структуру даних для інструкції, яка буде серіалізована у буфер байтів (instruction data). Ця структура залежить від логіки вашої програми. Кожна інструкція також потребує ID програми та масив адрес рахунків, з якими вона взаємодіє.
Приклад створення інструкції за допомогою бібліотеки @solana/web3.js:
import {
Connection,
PublicKey,
TransactionInstruction,
SystemProgram,
TransactionMessage,
VersionedTransaction,
Keypair,
LAMPORTS_PER_SOL
} from '@solana/web3.js';
// Приклад створення інструкції для переказу SOL
const transferInstruction = SystemProgram.transfer({
fromPubkey: senderAccount.publicKey,
toPubkey: recipientAccount.publicKey,
lamports: 0.1 * LAMPORTS_PER_SOL, // Переказ 0.1 SOL
});
// Приклад створення кастомної інструкції (структура даних залежить від вашої програми)
// const customInstructionData = Buffer.from([...]); // Серіалізовані дані інструкції
// const customInstruction = new TransactionInstruction({
// programId: customProgramId,
// keys: [...], // Масив { pubkey, isSigner, isWritable } для задіяних рахунків
// data: customInstructionData,
// });
2. Створення Повідомлення Транзакції
Для версіонованої транзакції використовується об'єкт TransactionMessage. Це повідомлення включає масив інструкцій та блокхеш (recentBlockhash), який використовується для визначення дійсності транзакції протягом певного часу. Якщо ви використовуєте ALTs, вам також потрібно буде включити інформацію про них у повідомлення.
// Отримання останнього блокхешу
const connection = new Connection('YOUR_RPC_URL');
const recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
// Створення повідомлення транзакції
const message = new TransactionMessage({
payerKey: senderAccount.publicKey, // Рахунок, який оплачує комісію
recentBlockhash: recentBlockhash,
instructions: [transferInstruction], // Масив інструкцій
// Якщо використовуєте ALTs, додайте lookupTableAccounts
// lookupTableAccounts: [...]
}).compileToV0Message(); // Компіляція у повідомлення версії 0
3. Створення Версіонованої Транзакції
Після створення повідомлення ви можете створити об'єкт VersionedTransaction, передавши повідомлення та масив підписів (спочатку порожній або з попередньо зібраними підписами).
const versionedTransaction = new VersionedTransaction(message);
4. Підписання Транзакції
Транзакція повинна бути підписана всіма рахунками, які позначені як isSigner: true у задіяних інструкціях. Зазвичай це рахунок відправника, який також є платником комісії.
versionedTransaction.sign([senderAccount]); // Підписання транзакції ключовою парою відправника
5. Відправлення та Підтвердження Транзакції
Підписану транзакцію можна відправити в мережу Solana за допомогою RPC-методу sendTransaction або sendAndConfirmTransaction. Важливо переконатися, що ваш RPC-клієнт підтримує версіоновані транзакції, вказуючи maxSupportedTransactionVersion: 0 або вище.
const signature = await connection.sendTransaction(versionedTransaction, {
skipPreflight: false, // Рекомендується залишити true для розробки, false для продакшену
});
console.log('Transaction sent with signature:', signature);
// Очікування підтвердження транзакції
const confirmation = await connection.confirmTransaction(signature, 'confirmed');
console.log('Transaction confirmed:', confirmation);
Додавання Власних Інструкцій
Щоб додати власні інструкції, які взаємодіють з вашою кастомною програмою, вам потрібно створити об'єкт TransactionInstruction для кожної такої інструкції. Це вимагає знання Program ID вашої програми, адрес рахунків, з якими вона взаємодіє, та формату даних інструкції, який очікує ваша програма. Дані інструкції зазвичай серіалізуються з визначеної структури даних у байтовий буфер.
Після створення об'єктів TransactionInstruction для ваших власних інструкцій, ви включаєте їх у масив instructions при створенні об'єкта TransactionMessage.
Це відео заглиблюється в технічні аспекти того, як транзакції на Solana компілюються та серіалізуються, що є важливим для розуміння формування даних інструкцій, особливо для власних програм.
Таблиця: Порівняння Legacy та Версіонованих Транзакцій
Нижче наведена таблиця, що узагальнює ключові відмінності між legacy та версіонованими транзакціями на Solana:
| Особливість | Legacy Транзакції | Версіоновані Транзакції (v0) |
|---|---|---|
| Формат повідомлення | Фіксований | Гнучкий, підтримує ALTs |
| Address Lookup Tables (ALTs) | Не підтримуються | Підтримуються |
| Максимальна кількість рахунків у повідомленні | Обмежена безпосереднім включенням | Значно більша за рахунок ALTs |
| Розмір транзакції | Фіксований ліміт | Більша ефективність використання простору |
| Сумісність з ончейн-програмами | Сумісні | Зазвичай сумісні (програми не вимагають змін) |
| Сумісність з клієнтськими додатками | Потрібна підтримка | Потребують оновлення для повної підтримки |
| Використання | Прості операції | Складні операції, DEX-свапи, тощо |
FAQ: Питання та Відповіді про Версіоновані Транзакції Solana
Чи потрібно оновлювати мої ончейн-програми для роботи з версіонованими транзакціями?
Зазвичай ні. Зміни до ончейн-програм НЕ потрібні для підтримки нової функціональності версіонованих транзакцій або для забезпечення зворотної сумісності. Основні зміни стосуються клієнтської сторони (SDK, гаманці, додатки), які повинні вміти створювати та обробляти версіоновані транзакції.
Як Address Lookup Tables (ALTs) допомагають зменшити розмір транзакцій?
ALTs дозволяють зберігати адреси рахунків ончейн у спеціальних таблицях. Замість того, щоб включати повні 32-байтові адреси рахунків безпосередньо в повідомлення транзакції, версіонована транзакція посилається на адресу в ALT за допомогою однобайтового індексу. Це суттєво зменшує обсяг даних, необхідних для представлення адрес рахунків у транзакції.
Чому мої RPC-запити можуть давати помилку при роботі з версіонованими транзакціями?
Якщо ваш RPC-клієнт (наприклад, використовує стару версію бібліотеки @solana/web3.js) не вказує підтримку версіонованих транзакцій (наприклад, не встановлено параметр maxSupportedTransactionVersion), і RPC-вузол намагається повернути вам версіоновану транзакцію (версії 0), ваш клієнт може не змогти її обробити і видати помилку. Переконайтеся, що ваша бібліотека та конфігурація RPC підтримують версіоновані транзакції.
Чи можна додати інструкції до існуючої версіонованої транзакції?
Ні, ви не можете просто "додати" інструкції до вже існуючого об'єкта VersionedTransaction. Транзакції на Solana є immutable після їх створення та підписання. Щоб включити нові інструкції, вам потрібно створити нове повідомлення транзакції (TransactionMessage), яке містить всі бажані інструкції, а потім створити нову версіоновану транзакцію з цим повідомленням.
Посилання
Last updated May 5, 2025