Допис
Діліться своїми знаннями.

Кодування BCS в Sui Що це таке і чому це важливо
Якщо ви будуєте на Sui або возите з Move, ви, напевно, чули термін BCS, що плаває навколо. Це скорочення від машини форматування Binary Canonical Serialization, спочатку створеної для блокчейну Diem, а тепер є наріжним каменем екосистем на основі MOVE, таких як Sui, Aptos, Starcoin та 0L.
Тож так, вам краще затишно з ним, якщо ви серйозно ставитеся до будівництва в цьому просторі.
Що таке BCS?
Бінарна канонічна серіалізація (BCS) - це формат, який використовується для серіалізації (кодування) та десеріалізації (декодування) структурованих даних у байти.
Ви побачите, що він використовується, коли:
- Кодування транзакцій перед підписанням.
- Випромінювання або аналіз подій з блокчейну.
- Взаємодія з Move смарт-контрактами поза ланцюжком за допомогою JavaScript.
Але BCS не включає інформацію про тип у байтах. Це означає, що ви повинні знати структуру заздалегідь під час декодування на відміну від форматів, таких як JSON або буфери протоколів, які більше самоописуються.
Ключові особливості BCS
Немає метаданих типу
Серіалізований вихід не містить підказок щодо типів полів. Ви повинні знати, з чим маєте справу, коли декодуєте.
Серіалізація, що залежить від замовлення
Структури кодуються в точному порядку їх полів. Змініть порядок, і ваша десеріалізація переривається. Ось чому функції peel_* у Move повинні відповідати макету структури 1:1.
Загальний тип
У структурі типу:
struct BCSObject<T> has drop, copy {
id: ID,
owner: address,
meta: Metadata,
generic: T
}
Ви можете надійно десеріалізувати лише до мета-поля. Загальні типи псуються з обробкою BCS, тому завжди ставте їх останніми, якщо ви хочете, щоб ваші дані були безпечно розшифровані.
Використання BCS в JavaScript
Завдяки бібліотеці @mysten /bcs ви можете працювати з BCS в JS як професіонал.
npm i @mysten/bcs
і основний приклад:
import { BCS, getSuiMoveConfig } from "@mysten/bcs";
const bcs = new BCS(getSuiMoveConfig());
const ser = bcs.ser(BCS.U16, 10);
console.log(ser.toBytes()); // [0x0a, 0x00]
const des = bcs.de(BCS.U16, ser.toBytes());
console.log(des); // 10
Ви також можете серіалізувати вектори та рядки:
bcs.ser("vector<u8>", [1, 2, 3, 4]); // 04 01 02 03 04
bcs.ser(BCS.STRING, "test string"); // 0b7465737420737472696e67
Реєстрація користувальницьких типів
Припустимо, у вас є такі структури переміщення:
struct Metadata has drop, copy {
name: std::ascii::String
}
struct BCSObject has drop, copy {
id: ID,
owner: address,
meta: Metadata
}
Ви можете зареєструвати їх так в JS:
bcs.registerStructType("Metadata", {
name: BCS.STRING,
});
bcs.registerStructType("BCSObject", {
id: BCS.ADDRESS,
owner: BCS.ADDRESS,
meta: "Metadata",
});
Приклад серіалізації та десеріалізації
Серіалізація JavaScript:
const bytes = bcs
.ser("BCSObject", {
id: "0x0000000000000000000000000000000000000005",
owner: "0x000000000000000000000000000000000000000a",
meta: { name: "aaa" }
})
.toString("hex");
console.log("Hex:", bytes);
Вихід може бути:
0x0000000000000000000000000000000000000005000000000000000000000000000000000000000a03616161
Тепер це можна передати в контракт Move або навіть перевірити вручну в Sui CLI.
BCS може виглядати низькорівневим і важким на байт, але як тільки ви зрозумієте, як він кодує дані, ви відкриєте глибше розуміння того, як насправді діють смарт-контракти Move — і як безпечно з'єднати позаланцюгові системи on-chain ↔.
І якщо ви налагоджуєте байти BCS на Sui Explorer (як наведений нижче):
Кодування BCS Бінарна канонічна серіалізація, або BCS, - це формат серіалізації, розроблений в контексті блокчейну Diem, і зараз широко використовується в більшості блокчейнів на основі Move (Sui, Starcoin, Aptos, 0L). BCS використовується не тільки в Move VM, але також використовується для кодування транзакцій та подій, наприклад, серіалізація транзакцій перед підписанням або аналіз даних подій.
Знання того, як працює BCS, має вирішальне значення, якщо ви хочете зрозуміти, як Move працює на більш глибокому рівні, і стати експертом Move. Давайте зануримося.
Специфікація та властивості BCS Є деякі властивості кодування BCS високого рівня, про які слід пам'ятати, коли ми проходимо решту уроку:
BCS - це формат серіалізації даних, де отримані вихідні байти не містять жодної інформації про тип; через це сторона, яка отримує закодовані байти, повинна знати, як десеріалізувати дані
У BCS немає структур (оскільки немає типів); структура просто визначає порядок, в якому поля серіалізуються
Типи обгортки ігноруються, тому outerType і UnnestedType матимуть однакове представлення BCS:
структура OuterType { власник: InnerType } структура innerType { адреса: адреса } структура UnstedType { адреса: адреса } Типи, що містять поля загального типу, можна обробляти до першого поля загального типу. Тож корисною практикою є розміщення поля загального типу останніми, якщо це спеціальний тип, який буде сер/де'd.
структура BCSobject
Примітивні типи, такі як непідписані int, кодуються у форматі Little Endian
Вектор серіалізується як довжина ULEB128 (з максимальною довжиною до u32), за якою слідує вміст вектора.
Повну специфікацію BCS можна знайти в сховищі BCS.
Використання бібліотеки JavaScript @mysten /bcs Установка Бібліотека, яку вам потрібно буде встановити для цієї частини, є бібліотека @mysten /bcs. Встановити його можна, ввівши в кореневому каталозі проекту вузла:
npm і @mysten /bcs Основний приклад Давайте спочатку скористаємося бібліотекою JavaScript для серіалізації та десеріалізації деяких простих типів даних:
імпорт {БКС, GETSUIMoveConfig} з "@mysten /bcs «;
//ініціалізуйте серіалізатор за допомогою конфігурацій Sui Move за замовчуванням const bcs = новий БКС (getSUIMoveConfig ());
//Визначте деякі типи тестових даних const ціле число = 10; масив const = [1, 2, 3, 4]; const string = «тестовий рядок»
//використовувати bcs.ser () для серіалізації даних
const ser_integer = bcs.ser (BCS.U16, ціле число);
//використовуйте bcs.de () для десеріалізації даних
const de_integer = bcs.de (BCS.U16, сер_цілі.тобайт ());
const de_array = bcs.de (
Давайте уважно розглянемо серіалізовані та десеріалізовані поля:
int — це маленькі ендіанські шістнадцятимельні числа
0а00 10
перший елемент вектора вказує на загальну довжину,
тоді це просто будь-які елементи у векторі
401020304 1,2,3,4
рядки - це просто вектори u8, при цьому перший елемент дорівнює довжині рядка
0б7465737420737472696е67 тестовий рядок Тип реєстрації Ми можемо зареєструвати власні типи, з якими ми будемо працювати, використовуючи наступний синтаксис:
імпорт {БКС, GETSUIMoveConfig} з "@mysten /bcs «; const bcs = новий БКС (getSUIMoveConfig ());
//Зареєструвати тип метаданих bcs.registerStructType («Метадані», { ім'я: БЦ.СТРИНГ, });
//Те саме для основного об'єкта, який ми маємо намір прочитати BCS.RegisterStructType («BCSobject», { //BCS.ADDRESS використовується для типів ідентифікаторів, а також типів адрес ідентифікатор: BCS.АДРЕСА, власник: БЦ.АДРЕСА, meta: «Метадані», }); Використання bcs у смарт-контрактах Sui Продовжимо наш приклад зверху зі структурами.
Визначення структури Почнемо з відповідних визначень структури в контракті Sui Move.
{ //.. Struct Метадані мають drop, copy { ім'я: std: :ascii: :Рядок }
структура BCSobject має drop, copy { ідентифікатор: Ідентифікатор, власник: адреса, meta: Метадані } //.. } Десеріалізація Тепер давайте напишемо функцію для десеріалізації об'єкта в контракті Sui.
//Ініціалізує екземпляр байтів bcs нехай bcs = bcs: :новий (bcs_байт);
//Використовуйте peel_*
функції для видалення значень із серіалізованих байтів.
//Порядок повинен бути таким же, як ми використовували в серіалізації!
let (ідентифікатор, власник, мета) = (
bcs:: адреса_вилучення (& мут bcs), bcs:: адреса_відклеювання (& мут bcs), bcs:: peel_vec_u8 (& мут bcs)
);
//Упакуйте структуру BCSObject з результатами серіалізації
BCSObject {id: об'єкт: :id_з_адреси (id), власник, мета: Метадані {ім'я: std: :ascii: :рядок (мета)}}}
Методи peel_*, що варіюються в модулі Sui Frame bcs, використовуються для «очищення» кожного окремого поля з серіалізованих байтів BCS. Зверніть увагу, що порядок, яким ми очищаємо поля, повинен бути точно таким же, як порядок полів у визначенні struct.
Тест: Чому результати не однакові з перших двох викликів peel_address на одному об'єкті bcs?
Також зверніть увагу на те, як ми перетворюємо типи з адреси в id, а з вектора в <8>std: :ascii: :string за допомогою допоміжних функцій.
Тест: Що станеться, якби BSCobject мав тип UID замість типу ідентифікатора?
Повний приклад Ser/De Знайдіть повні зразки кодів JavaScript та Sui Move у папці example_projects.
Спочатку серіалізуємо тестовий об'єкт за допомогою програми JavaScript:
//Будуємо тестовий об'єкт для серіалізації, зауважте, що ми можемо вказати формат виводу на hex нехай _байтів = bcs .ser («BCSObject», { ідентифікатор: «0x00000000000000000000000000000000000000000005», власник: «0x0000000000000000000000000000000000000000000а», мета: {ім'я: «ааа"} }) .toString («шестигранник»); Ми хочемо, щоб вихід запису BCS цього разу був у шістнадцятковому форматі, який можна вказати, як вище.
Прикріпіть шестирядку результату серіалізації префіксом 0x та експортуйте до змінної середовища:
експортувати об'єкт_HexString = 0x000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000А03616161 Тепер ми можемо або запустити пов'язані тести Move unit, щоб перевірити правильність:
тест на самостійний рух Ви повинні побачити це в консолі:
БУДІВНИЦТВО bcs_move Запуск тестів Move unit [ПРОПУСК] 0x0: :bcs_object: :тест_десеріалізація Результат тесту: ОК. Всього тестів: 1; пройдено: 1; не вдалося: 0 Або ми можемо опублікувати модуль (і експортувати PACKAGE_ID) і викликати метод emit_object за допомогою наведеного вище BCS серіалізованого шестирядка:
власний виклик клієнта --функція emit_object --модуль bcs_object --package $PACKAGE_ID --аргс $OBJECT_HEXSTRING Потім ми можемо перевірити вкладку Події транзакції на Sui Explorer, щоб побачити, що ми випустили правильно десеріалізований BCSObject:
- Sui
- SDKs and Developer Tools
Що таке лтл-ендіан і біг-ендіан?
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Зароби свою частку з 1000 Sui
Заробляй бали репутації та отримуй винагороди за допомогу в розвитку спільноти Sui.

- 0xduckmove... SUI+88
1
- harry phan... SUI+61
2
- MiniBob... SUI+57
3
- ... SUIHaGiang+56
- ... SUIRogue+47
- ... SUIRogueRig+44
- ... SUIPeera Admin+25
- ... SUIVens.sui+20
- ... SUIMarlKey+20
- ... SUIdudley_smith+16