Bài viết
Chia sẻ kiến thức của bạn.

Mã hóa BCS trong Sui Nó là gì và tại sao nó quan trọng
Nếu bạn đang xây dựng trên Sui hoặc mày mò với Move, có lẽ bạn đã nghe đến thuật ngữ BCS trôi nổi xung quanh. Đó là viết tắt của máy định dạng Binary Canonical Serialization ban đầu được tạo ra cho blockchain Diem và hiện là nền tảng của các hệ sinh thái dựa trên Move như Sui, Aptos, Starcoin và 0L.
Vì vậy, vâng, tốt hơn hết bạn nên ấm cúng với nó nếu bạn nghiêm túc với việc xây dựng trong không gian này.
BCS là gì?
Binary Canonical Serialization (BCS) là một định dạng được sử dụng để tuần tự hóa (mã hóa) và giải mã (giải mã) dữ liệu có cấu trúc thành byte.
Bạn sẽ thấy nó được sử dụng khi:
- Mã hóa giao dịch trước khi ký.
- Phát ra hoặc phân tích các sự kiện từ blockchain.
- Tương tác với Move smart contract off-chain thông qua JavaScript.
Nhưng BCS không bao gồm thông tin kiểu trong byte. Điều này có nghĩa là bạn phải biết cấu trúc trước khi giải mã không giống như các định dạng như JSON hoặc Protocol Buffers, vốn tự mô tả nhiều hơn.
Các tính năng chính của BCS
Không có loại siêu dữ liệu
Đầu ra được nối tiếp không chứa gợi ý về loại trường. Bạn phải biết bạn đang đối mặt với những gì khi bạn giải mã.
Sê-ri hóa phụ thuộc vào đơn hàng
Các cấu trúc được mã hóa theo thứ tự chính xác của các trường của chúng. Thay đổi thứ tự và quá trình khử chuỗi của bạn bị ngắt. Đây là lý do tại sao các hàm peel_* trong Move phải khớp với bố cục của struct 1:1.
Loại chung
Trong một cấu trúc như:
struct BCSObject<T> has drop, copy {
id: ID,
owner: address,
meta: Metadata,
generic: T
}
Bạn chỉ có thể giải mã hóa một cách đáng tin cậy cho đến trường meta. Các loại chung gây rối với phân tích cú pháp BCS, vì vậy hãy luôn đặt chúng cuối cùng nếu bạn muốn dữ liệu của mình được giải mã một cách an toàn.
Sử dụng BCS trong JavaScript
Nhờ thư viện @mysten /bcs, bạn có thể làm việc với BCS trong JS như một chuyên gia.
npm i @mysten/bcs
và ví dụ cơ bản:
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
Bạn cũng có thể tuần tự hóa vectơ và chuỗi:
bcs.ser("vector<u8>", [1, 2, 3, 4]); // 04 01 02 03 04
bcs.ser(BCS.STRING, "test string"); // 0b7465737420737472696e67
Đăng ký các loại tùy chỉnh
Giả sử bạn có cấu trúc Move sau:
struct Metadata has drop, copy {
name: std::ascii::String
}
struct BCSObject has drop, copy {
id: ID,
owner: address,
meta: Metadata
}
Bạn có thể đăng ký chúng như thế này trong JS:
bcs.registerStructType("Metadata", {
name: BCS.STRING,
});
bcs.registerStructType("BCSObject", {
id: BCS.ADDRESS,
owner: BCS.ADDRESS,
meta: "Metadata",
});
Ví dụ về sê-ri hóa & giải mã
Trình tự hóa JavaScript:
const bytes = bcs
.ser("BCSObject", {
id: "0x0000000000000000000000000000000000000005",
owner: "0x000000000000000000000000000000000000000a",
meta: { name: "aaa" }
})
.toString("hex");
console.log("Hex:", bytes);
Đầu ra có thể:
0x0000000000000000000000000000000000000005000000000000000000000000000000000000000a03616161
Điều này bây giờ có thể được chuyển vào hợp đồng Move hoặc thậm chí kiểm tra thủ công trong Sui CLI.
BCS có thể trông cấp thấp và nặng byte, nhưng một khi bạn hiểu cách nó mã hóa dữ liệu, bạn sẽ hiểu sâu hơn về cách hợp đồng thông minh Move thực sự hoạt động như thế nào - và cách kết nối các hệ thống ngoài chuỗi trên chuỗi ↔ một cách an toàn.
Và nếu bạn đang gỡ lỗi byte BCS trên Sui Explorer (như bên dưới):
Mã hóa BCS Binary Canonical Serialization, hay BCS, là một định dạng chuỗi hóa được phát triển trong bối cảnh của chuỗi khối Diệm, và hiện được sử dụng rộng rãi trong hầu hết các blockchain dựa trên Move (Sui, Starcoin, Aptos, 0L). BCS không chỉ được sử dụng trong Move VM, mà còn được sử dụng trong mã hóa giao dịch và sự kiện, chẳng hạn như sắp xếp các giao dịch trước khi ký, hoặc phân tích dữ liệu sự kiện.
Biết cách thức hoạt động của BCS là rất quan trọng nếu bạn muốn hiểu cách Move hoạt động ở mức độ sâu hơn và trở thành chuyên gia Move. Hãy đi sâu vào.
Đặc điểm kỹ thuật và tính chất của BCS Có một số thuộc tính cấp cao của mã hóa BCS cần lưu ý khi chúng ta xem qua phần còn lại của bài học:
BCS là một định dạng chuỗi hóa dữ liệu trong đó các byte đầu ra kết quả không chứa bất kỳ thông tin kiểu nào; vì điều này, bên nhận các byte được mã hóa sẽ cần biết cách giải mã hóa dữ liệu
Không có cấu trúc trong BCS (vì không có kiểu); cấu trúc chỉ đơn giản xác định thứ tự mà các trường được nối tiếp
Các loại Wrapper bị bỏ qua, vì vậy OuterType và UnnestedType sẽ có cùng một biểu diễn BCS:
cấu trúc OuterType { chủ sở hữu: InnerType } cấu trúc innerType { địa chỉ: địa chỉ } cấu trúc unnestedType { địa chỉ: địa chỉ } Các loại chứa các trường kiểu chung có thể được phân tích cú pháp cho đến trường kiểu chung đầu tiên. Vì vậy, bạn nên đặt (các) trường kiểu chung cuối cùng nếu đó là kiểu tùy chỉnh sẽ được ser/de'd.
struct BCSObject
Các kiểu nguyên thủy như int không dấu được mã hóa ở định dạng Little Endian
Vector được nối tiếp thành độ dài ULEB128 (với chiều dài tối đa lên đến u32) theo sau là nội dung của vectơ.
Thông số kỹ thuật đầy đủ của BCS có thể được tìm thấy trong kho lưu trữ BCS.
Sử dụng Thư viện JavaScript @mysten /bcs Lắp đặt Thư viện bạn sẽ cần cài đặt cho phần này là thư viện @mysten /bcs. Bạn có thể cài đặt nó bằng cách nhập vào thư mục gốc của dự án nút:
npm ở @mysten /bcs Ví dụ cơ bản Trước tiên, chúng ta hãy sử dụng thư viện JavaScript để tuần tự hóa và khử sê-ri một số kiểu dữ liệu đơn giản:
nhập {BCS, getsuimoveConfig} từ "@mysten /bcs “;
//khởi tạo trình tuần tự với cấu hình Sui Move mặc định const bcs = BCS mới (getSUIMoveConfig ());
//Xác định một số kiểu dữ liệu thử nghiệm const integer = 10; mảng const = [1, 2, 3, 4]; const string = “chuỗi thử nghiệm”
//sử dụng bcs.ser () để nối tiếp dữ liệu
const ser_integer = bcs.ser (BCS.U16, số nguyên);
//sử dụng bcs.de () để giải mã dữ liệu
const de_integer = bcs.de (BCS.U16, SER_integer.tobytes ());
const de_array = bcs.de (“vector
Chúng ta hãy xem xét kỹ các trường được nối tiếp và giải mã hóa:
int là số thập lục phân little-endian
0a00 10
phần tử đầu tiên của vectơ cho biết tổng chiều dài,
thì nó chỉ là bất kỳ phần tử nào trong vectơ
4001020304 1,2,3,4
string chỉ là vectơ của u8, với phần tử đầu tiên bằng chiều dài của chuỗi
0b7465737420737472696e67 chuỗi kiểm tra Loại đăng ký Chúng tôi có thể đăng ký các loại tùy chỉnh mà chúng tôi sẽ làm việc bằng cú pháp sau:
nhập {BCS, getsuimoveConfig} từ "@mysten /bcs “; const bcs = BCS mới (getSUIMoveConfig ());
//Đăng ký loại siêu dữ liệu bcs.registerStructType (“Siêu dữ liệu”, { Tên: BCS.STRING, });
//Tương tự đối với đối tượng chính mà chúng tôi dự định đọc bcs.registerStructType (“BCSObject”, { //BCS.ADDRESS được sử dụng cho các loại ID cũng như các loại địa chỉ ID: BCS.ADDRESS, chủ sở hữu: BCS.ADDRESS, meta: “Siêu dữ liệu”, }); Sử dụng bcs trong Hợp đồng thông minh Sui Hãy tiếp tục ví dụ của chúng tôi từ phía trên với các cấu trúc.
Định nghĩa cấu trúc Chúng ta bắt đầu với các định nghĩa cấu trúc tương ứng trong hợp đồng Sui Move.
{ //.. struct Siêu dữ liệu có drop, copy { Tên: std: :ascii: :String }
struct BCSObject có drop, copy { ID: ID, chủ sở hữu: địa chỉ, meta: Siêu dữ liệu } //.. } Không phân loại hóa Bây giờ, chúng ta hãy viết hàm để giải mã một đối tượng trong hợp đồng Sui.
//Khởi tạo phiên bản bcs bytes hãy để bcs = bcs: :mới (bcs_bytes);
//Sử dụng các peel_*
hàm để bóc các giá trị từ các byte được nối tiếp.
//Thứ tự phải giống như chúng tôi đã sử dụng trong quá trình nối tiếp!
let (id, chủ sở hữu, meta) = (
bcs: :địa chỉ peel_( & mut bcs), bcs:: địa chỉ peel_( & mut bcs), bcs:: peel_vec_u8 (& mut bcs)
);
//Đóng gói cấu trúc BCSObject với kết quả sắp xếp sê-ri
BCSObject {id: object: :id_from_address (id), chủ sở hữu, meta: Siêu dữ liệu {tên: std: :ascii: :chuỗi (meta)}}}
Các phương thức peel_* khác nhau trong mô-đun Sui Frame bcs được sử dụng để “bóc” từng trường riêng lẻ từ các byte nối tiếp BCS. Lưu ý rằng thứ tự chúng ta bóc các trường phải hoàn toàn giống với thứ tự của các trường trong định nghĩa cấu trúc.
Trắc nghiệm: Tại sao kết quả không giống nhau từ hai cuộc gọi peel_address đầu tiên trên cùng một đối tượng bcs?
Cũng lưu ý cách chúng ta chuyển đổi các kiểu từ địa chỉ sang id và từ vector <8>sang std: :ascii: :string với các hàm trợ giúp.
Trắc nghiệm: Điều gì sẽ xảy ra nếu BSCobject có kiểu UID thay vì loại ID?
Hoàn thành ví dụ Ser/De Tìm mã mẫu JavaScript và Sui Move đầy đủ trong thư mục example_projects.
Đầu tiên, chúng tôi tuần tự hóa một đối tượng thử nghiệm bằng chương trình JavaScript:
//Chúng tôi xây dựng một đối tượng thử nghiệm để nối tiếp, lưu ý rằng chúng tôi có thể chỉ định định dạng của đầu ra thành hex cho _byte = bcs .ser (“bcsObject”, { id: “0x0000000000000000000000000000000000000005", chủ sở hữu: “0x000000000000000000000000000000000000000a”, meta: {name: “aaa"} }) .toString (“hex”); Chúng tôi muốn đầu ra của trình ghi BCS lần này ở định dạng thập lục phân, có thể được chỉ định như ở trên.
Dán kết quả chuỗi hóa hexstring với tiền tố 0x và xuất sang biến môi trường:
xuất object_hexstring=0x00000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000a03616161 Bây giờ chúng ta có thể chạy các bài kiểm tra đơn vị Move liên quan để kiểm tra tính chính xác:
kiểm tra sui move Bạn sẽ thấy điều này trong bảng điều khiển:
XÂY DỰNG bcs_move Chạy thử nghiệm đơn vị Move [PASS] 0x0: :bcs_object: :test_deserialization Kết quả kiểm tra: OK. Tổng số bài kiểm tra: 1; vượt qua: 1; thất bại: 0 Hoặc chúng ta có thể xuất bản mô-đun (và xuất PACKAGE_ID) và gọi phương thức emit_object bằng cách sử dụng chuỗi lục giác nối tiếp BCS ở trên:
gọi máy khách riêng --function emit_object --module bcs_object --package $PACKAGE_ID --args $OBJECT_HEXSTRING Sau đó, chúng tôi có thể kiểm tra tab Sự kiện của giao dịch trên Sui Explorer để xem chúng tôi đã phát ra BCSobject được giải mã chính xác hay không:
- Sui
- SDKs and Developer Tools
Little-endian và big-endian là gì?
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Kiếm phần của bạn từ 1000 Sui
Tích lũy điểm danh tiếng và nhận phần thưởng khi giúp cộng đồng Sui phát triển.

- 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