Publicación
Comparte tu conocimiento.

Codificación BCS en Sui: qué es y por qué es importante
Si te estás basando en Sui o jugando con Move, es probable que hayas escuchado el término BCS por ahí. Es la abreviatura de la máquina formateadora de serialización canónica binaria creada originalmente para la cadena de bloques Diem, y ahora es la piedra angular de los ecosistemas basados en Move, como Sui, Aptos, Starcoin y 0L.
Así que sí, es mejor que te sientas cómodo con ello si realmente quieres construir en este espacio.
¿Qué es BCS?
La serialización canónica binaria (BCS) es un formato que se utiliza para serializar (codificar) y deserializar (decodificar) datos estructurados en bytes.
Verás que se usa cuando:
- Codificar las transacciones antes de firmarlas.
- Emitir o analizar eventos desde la cadena de bloques.
- Interactuar con Move Smart Contracts fuera de la cadena a través de JavaScript.
Sin embargo, BCS no incluye información de tipos en los bytes. Esto significa que debes conocer la estructura con antelación al decodificar, a diferencia de los formatos como JSON o Protocol Buffers, que se describen más por sí mismos.
Características principales de BCS
No hay ningún tipo de metadatos
La salida serializada no contiene sugerencias sobre los tipos de campos. Debes saber a qué te enfrentas cuando decodificas.
Serialización dependiente del pedido
Las estructuras se codifican en el orden exacto de sus campos. Cambie el orden y la deserialización se interrumpirá. Esta es la razón por la que las funciones peel_* de Move deben coincidir con el diseño 1:1.
Tipo genérico
En una estructura como:
struct BCSObject<T> has drop, copy {
id: ID,
owner: address,
meta: Metadata,
generic: T
}
Solo puede deserializar de forma fiable hasta el metacampo. Los tipos genéricos estropean el análisis del BCS, así que póngalos siempre en último lugar si desea que sus datos se decodifiquen de forma segura.
Uso de BCS en JavaScript
Gracias a la biblioteca @mysten /bcs, puedes trabajar con BCS en JS como un profesional.
npm i @mysten/bcs
y un ejemplo básico:
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
También puede serializar vectores y cadenas:
bcs.ser("vector<u8>", [1, 2, 3, 4]); // 04 01 02 03 04
bcs.ser(BCS.STRING, "test string"); // 0b7465737420737472696e67
Registro de tipos personalizados
Supongamos que tienes las siguientes estructuras de movimiento:
struct Metadata has drop, copy {
name: std::ascii::String
}
struct BCSObject has drop, copy {
id: ID,
owner: address,
meta: Metadata
}
Puedes registrarlos así en JS:
bcs.registerStructType("Metadata", {
name: BCS.STRING,
});
bcs.registerStructType("BCSObject", {
id: BCS.ADDRESS,
owner: BCS.ADDRESS,
meta: "Metadata",
});
Ejemplo de serialización y deserialización
Serialización de JavaScript:
const bytes = bcs
.ser("BCSObject", {
id: "0x0000000000000000000000000000000000000005",
owner: "0x000000000000000000000000000000000000000a",
meta: { name: "aaa" }
})
.toString("hex");
console.log("Hex:", bytes);
La salida puede ser:
0x0000000000000000000000000000000000000005000000000000000000000000000000000000000a03616161
Esto ahora puede transferirse a un contrato de Move o incluso probarse manualmente en la CLI de Sui.
El BCS puede parecer de bajo nivel y con muchos bytes, pero una vez que comprendas cómo codifica los datos, comprenderás mejor cómo funcionan realmente los contratos inteligentes de Move y cómo conectar sistemas on-chain ↔ off-chain de forma segura.
Y si estás depurando los bytes del BCS en Sui Explorer (como el que se muestra a continuación):
Codificación BCS La serialización canónica binaria, o BCS, es un formato de serialización desarrollado en el contexto de la cadena de bloques Diem, y ahora se usa ampliamente en la mayoría de las cadenas de bloques basadas en Move (Sui, Starcoin, Aptos, 0L). El BCS no solo se usa en la máquina virtual Move, sino que también se usa en la codificación de transacciones y eventos, como la serialización de las transacciones antes de firmarlas o el análisis de datos de eventos.
Saber cómo funciona BCS es crucial si quieres entender cómo funciona Move a un nivel más profundo y convertirte en un experto en Move. Vamos a sumergirnos.
Especificaciones y propiedades del BCS Hay algunas propiedades de alto nivel de la codificación BCS que conviene tener en cuenta a medida que avancemos en el resto de la lección:
El BCS es un formato de serialización de datos en el que los bytes de salida resultantes no contienen ningún tipo de información; por ello, la parte que reciba los bytes codificados necesitará saber cómo deserializar los datos
En BCS no hay estructuras (ya que no hay tipos); la estructura simplemente define el orden en el que se serializan los campos
Los tipos de contenedores se ignoran, por lo que OuterType y UnnestedType tendrán la misma representación de BCS:
estructura: outerType { propietario: innerType } estructura InnerType { dirección: dirección } estructura UnnestedType { dirección: dirección } Los tipos que contienen los campos de tipo genérico se pueden analizar hasta el primer campo de tipo genérico. Por lo tanto, es una buena práctica poner los campos de tipo genérico en último lugar si se trata de un tipo personalizado que se va a ser/eliminar.
Los tipos primitivos, como las entradas sin signo, están codificados en formato Little Endian
El vector se serializa con una longitud ULEB128 (con una longitud máxima de hasta u32) seguida del contenido del vector.
La especificación BCS completa se encuentra en el repositorio BCS.
Uso de la biblioteca de JavaScript @mysten /bcs Instalación La biblioteca que necesitará instalar para esta parte es la biblioteca @mysten /bcs. Puedes instalarla escribiendo en el directorio raíz de un proyecto de nodo:
npm i @mysten /bcs Ejemplo básico Utilicemos primero la biblioteca de JavaScript para serializar y deserializar algunos tipos de datos simples:
importar {BCS, getSuiMoveConfig} desde "@mysten /bcs «;
//inicializa el serializador con las configuraciones predeterminadas de Sui Move const bcs = new BCS (getSuiMoveConfig ());
//Definir algunos tipos de datos de prueba entero constante = 10; matriz constante = [1, 2, 3, 4]; const string = «cadena de prueba»
//usa bcs.ser () para serializar los datos
const ser_integer = bcs.ser (BCS.U16, entero);
//usa bcs.de () para deserializar datos
const de_integer = bcs.de (BCS.U16, SER_Integer.toBytes ());
Echemos un vistazo más de cerca a los campos serializados y deserializados:
las entradas son hexadecimales mendianos
0a00 10
el primer elemento de un vector indica la longitud total,
entonces son los elementos que están en el vector
0401020304 1,2,3,4
las cadenas son solo vectores de u8, con el primer elemento igual a la longitud de la cadena
0b7465737420737472696e67 cadena de prueba Escriba el registro Podemos registrar los tipos personalizados con los que trabajaremos usando la siguiente sintaxis:
importar {BCS, getSuiMoveConfig} desde "@mysten /bcs «; const bcs = new BCS (getSuiMoveConfig ());
//Registrar el tipo de metadatos bcs.registerStructType («Metadatos», { nombre: BCS.STRING, });
//Lo mismo para el objeto principal que pretendemos leer bcs.registerStructType («bcsObject», { //BCS.ADDRESS se usa tanto para tipos de ID como para tipos de direcciones id: BCS.ADDRESS, propietario: BCS.ADDRESS, meta: «Metadatos», }); Uso de bcs en Sui Smart Contracts Continuemos con nuestro ejemplo de arriba con las estructuras.
Definición de estructura Empezamos con las definiciones de estructura correspondientes en el contrato Sui Move.
{ //.. estructura Los metadatos han eliminado, copiado { nombre: std: :ascii: :String }
struct bcSObject ha caído, copia { id: ID, propietario: dirección, meta: Metadatos } //.. } Deserialización Ahora, escribamos la función para deserializar un objeto en un contrato Sui.
//Inicializa la instancia de bcs bytes let bcs = bcs: :new (bcs_bytes);
//Usa peel_*
funciones para eliminar los valores de los bytes serializados.
//¡El orden tiene que ser el mismo que usamos en la serialización!
let (id, owner, meta) = (
bcs: :peel_address (&mut bcs), bcs: :peel_address (&mut bcs), bcs: :peel_vec_u8 (&mut bcs)
);
//Empaquete una estructura BCSObject con los resultados de la serialización
BCSObject {id: object: :id_from_address (id), owner, meta: Metadata {name: std: :ascii: :string (meta)}}
Los distintos métodos peel_* del módulo bcs de Sui Frame se utilizan para «separar» cada campo individual de los bytes serializados de BCS. Tenga en cuenta que el orden en que eliminamos los campos debe ser exactamente el mismo que el orden de los campos en la definición de la estructura.
Cuestionario: ¿Por qué los resultados de las dos primeras llamadas a peel_address en el mismo objeto bcs no son los mismos?
Observa también cómo convertimos los tipos de address a id y de vector <8>a std: :ascii: :string con funciones auxiliares.
Cuestionario: ¿Qué pasaría si BSCobject tuviera un tipo de UID en lugar de un tipo de ID?
Ejemplo completo de Ser/De Encuentra los códigos de muestra completos de JavaScript y Sui Move en la carpeta example_projects.
Primero, serializamos un objeto de prueba usando el programa JavaScript:
//Construimos un objeto de prueba para serializarlo, ten en cuenta que podemos especificar el formato de la salida en hexadecimal let _bytes = bcs .ser («bcsObject», { id: «0x00000000000000000000000000000005", propietario: «0x0000000000000000000000000000000a», meta: {nombre: «aaa"} }) .toString («hexadecimal»); Queremos que la salida del escritor BCS esté en formato hexadecimal esta vez, que se puede especificar como se indica arriba.
Añada el prefijo 0x a la cadena hexadecimal del resultado de la serialización y expórtela a una variable de entorno:
export Object_hexstring=0x000000000000000000000000000000000005000000000000000000000000000000000000000000000000000A03616161 Ahora podemos ejecutar las pruebas unitarias de Move asociadas para comprobar que son correctas:
Una prueba de movimiento adecuada Deberías ver esto en la consola:
CONSTRUYENDO bcs_move Ejecutando pruebas unitarias de Move [PASS] 0x0: :bcs_object: :test_deserialization Resultado de la prueba: OK. Total de pruebas: 1; superadas: 1; fallidas: 0 O podemos publicar el módulo (y exportar el PACKAGE_ID) y llamar al método emit_object utilizando la cadena hexagonal serializada de BCS anterior:
sui client call --function emit_object --module bcs_object --package $PACKAGE_ID --args $OBJECT_HEXSTRING A continuación, podemos comprobar la pestaña Eventos de la transacción en el explorador Sui para comprobar que hemos emitido el BCSObject deserializado correctamente:
- Sui
- SDKs and Developer Tools
¿Qué es little-endian y big-endian?
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
Gana tu parte de 1000 Sui
Gana puntos de reputación y obtén recompensas por ayudar a crecer a la comunidad de 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