Підсумок
Інструкція має 3 поля: program_id (яку програму викликати), accounts
(список AccountMeta з прапорцями is_signer/is_writable) та data (масив
байтів даних, які інтерпретує програма).
Структура інструкції
Instruction
складається з трьох полів:
program_id: ID програми, яка викликається.accounts: Масив метаданих акаунтаdata: Масив байтів з додатковими даними для використання інструкцією.
pub struct Instruction {/// Pubkey of the program that executes this instruction.pub program_id: Pubkey,/// Metadata describing accounts that should be passed to the program.pub accounts: Vec<AccountMeta>,/// Opaque data passed to the program for its own interpretation.pub data: Vec<u8>,}
ID програми
program_id інструкції — це адреса
публічного ключа програми, яка містить логіку виконання інструкції. Середовище
виконання використовує це поле для маршрутизації інструкції до правильної
програми для обробки.
Метадані акаунта
Масив accounts інструкції — це впорядкований список структур
AccountMeta.
Метадані мають бути надані для кожного акаунта, з яким взаємодіє інструкція.
Валідатор використовує ці метадані для визначення, які транзакції можуть
виконуватися паралельно. Транзакції, які записують у різні акаунти, можуть
виконуватися паралельно.
Діаграма нижче показує транзакцію, яка містить одну інструкцію. Масив accounts
інструкції містить метадані для двох акаунтів.
Транзакція з однією інструкцією. Інструкція містить дві структури AccountMeta у своєму масиві accounts.
Кожна структура AccountMeta має три поля:
- pubkey: Адреса публічного ключа акаунта
- is_signer: Встановлюється в
true, якщо акаунт повинен підписати транзакцію - is_writable: Встановлюється в
true, якщо інструкція змінює дані акаунта
Щоб дізнатися, які облікові записи потрібні інструкції, включаючи те, які мають бути доступними для запису, лише для читання або підписувати транзакцію, ви повинні звернутися до реалізації інструкції, як визначено програмою.
pub struct AccountMeta {/// An account's public key.pub pubkey: Pubkey,/// True if an `Instruction` requires a `Transaction` signature matching `pubkey`.pub is_signer: bool,/// True if the account data or metadata may be mutated during program execution.pub is_writable: bool,}
Дані
Поле data інструкції — це масив байтів, який повідомляє програмі, яку функцію
викликати, і надає аргументи для цієї функції. Дані зазвичай починаються з
дискримінатора або індексного байта (байтів), що ідентифікує цільову функцію, за
якими слідують серіалізовані аргументи. Формат кодування визначається кожною
програмою (наприклад, серіалізація Borsh або власний макет).
Поширені конвенції кодування:
- Основні програми (System, Stake, Vote): використовують індекс варіанта enum, серіалізованого Bincode, за яким слідують серіалізовані аргументи.
- Програми Anchor: використовують 8-байтовий дискримінатор (перші 8 байтів
SHA-256 хешу
"global:<function_name>"), за яким слідують аргументи, серіалізовані Borsh.
Середовище виконання не інтерпретує поле data. Воно передається як є до точки
входу process_instruction програми.
Скомпільована інструкція
Коли інструкції серіалізуються в повідомлення транзакції, вони стають
структурами
CompiledInstruction,
які замінюють усі публічні ключі компактними цілочисельними індексами в масиві
account_keys повідомлення.
Приклад: інструкція переказу SOL
Приклад нижче показує структуру інструкції переказу SOL.
import { generateKeyPairSigner, lamports } from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();// Define the amount to transferconst LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount});console.log(JSON.stringify(transferInstruction, null, 2));
Код нижче показує вивід з попередніх фрагментів коду. Формат буде відрізнятися
між SDK, але зверніть увагу, що кожна інструкція містить ті самі три обов'язкові
частини інформації: program_id,
accounts, data.
{"accounts": [{"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","role": 3,"signer": {"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","keyPair": {"privateKey": {},"publicKey": {}}}},{"address": "2mBY6CTgeyJNJDzo6d2Umipw2aGUquUA7hLdFttNEj7p","role": 1}],"programAddress": "11111111111111111111111111111111","data": {"0": 2,"1": 0,"2": 0,"3": 0,"4": 128,"5": 150,"6": 152,"7": 0,"8": 0,"9": 0,"10": 0,"11": 0}}
Наведені нижче приклади показують, як вручну створити інструкцію переказу.
(Вкладка Expanded Instruction функціонально еквівалентна вкладці
Instruction.)
На практиці вам зазвичай не потрібно створювати Instruction вручну.
Більшість програм надають клієнтські бібліотеки з допоміжними функціями, які
створюють інструкції за вас. Якщо бібліотека недоступна, ви можете створити
інструкцію вручну.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?