Sui.

Publication

Partagez vos connaissances.

article banner.
0xduckmove.
May 30, 2025
Article

L'encodage BCS dans Sui : qu'est-ce que c'est et pourquoi c'est important

Si vous vous basez sur Sui ou que vous bricolez avec Move, vous avez probablement entendu le terme BCS circuler. C'est l'abréviation de la machine de formatage de sérialisation canonique binaire conçue à l'origine pour la blockchain Diem, et qui constitue désormais la pierre angulaire des écosystèmes basés sur Move tels que Sui, Aptos, Starcoin et 0L.

Alors oui, tu ferais mieux de t'y mettre à l'aise si tu veux vraiment construire dans cet espace.

Qu'est-ce que BCS ?

La sérialisation canonique binaire (BCS) est un format utilisé pour sérialiser (encoder) et désérialiser (décoder) des données structurées en octets.

Vous le verrez utilisé lorsque :

  • Encodage des transactions avant de les signer.
  • Émettre ou analyser des événements depuis la blockchain.
  • Interagir avec les contrats intelligents Move off-chain via JavaScript.

Mais BCS n'inclut pas d'informations de type dans les octets. Cela signifie que vous devez connaître la structure à l'avance lors du décodage, contrairement aux formats tels que JSON ou Protocol Buffers, qui sont plus autodescriptifs.

Principales caractéristiques de BCS

Aucune métadonnée de type

La sortie sérialisée ne contient aucune indication sur les types de champs. Vous devez savoir à quoi vous avez affaire lorsque vous décodez.

Sérialisation dépendante de l'ordre

Les structures sont codées dans l'ordre exact de leurs champs. Modifiez l'ordre et votre désérialisation s'interrompt. C'est pourquoi les fonctions peel_* de Move doivent correspondre à la disposition 1:1. de la structure.

Type générique

Dans une structure comme :

struct BCSObject<T> has drop, copy {
    id: ID,
    owner: address,
    meta: Metadata,
    generic: T
}

Vous ne pouvez désérialiser de manière fiable que jusqu'au champ méta. Les types génériques perturbent l'analyse BCS, alors mettez-les toujours en dernier si vous voulez que vos données soient décodées en toute sécurité.

Utilisation de BCS en JavaScript

Grâce à la bibliothèque @mysten /bcs, vous pouvez travailler avec BCS dans JS comme un pro.

npm i @mysten/bcs

et exemple de base :

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

Vous pouvez également sérialiser des vecteurs et des chaînes :

bcs.ser("vector<u8>", [1, 2, 3, 4]); // 04 01 02 03 04
bcs.ser(BCS.STRING, "test string"); // 0b7465737420737472696e67

Enregistrement de types personnalisés

Supposons que vous ayez les structures Move suivantes :

struct Metadata has drop, copy {
    name: std::ascii::String
}

struct BCSObject has drop, copy {
    id: ID,
    owner: address,
    meta: Metadata
}


Vous pouvez les enregistrer comme ceci dans JS :

bcs.registerStructType("Metadata", {
  name: BCS.STRING,
});

bcs.registerStructType("BCSObject", {
  id: BCS.ADDRESS,
  owner: BCS.ADDRESS,
  meta: "Metadata",
});

Exemple de sérialisation et de désérialisation

Sérialisation JavaScript :

const bytes = bcs
  .ser("BCSObject", {
    id: "0x0000000000000000000000000000000000000005",
    owner: "0x000000000000000000000000000000000000000a",
    meta: { name: "aaa" }
  })
  .toString("hex");

console.log("Hex:", bytes);

La sortie peut être :

0x0000000000000000000000000000000000000005000000000000000000000000000000000000000a03616161

Cela peut désormais être transféré dans un contrat Move ou même testé manuellement dans Sui CLI.

Le BCS peut sembler de bas niveau et riche en octets, mais une fois que vous aurez compris comment il code les données, vous pourrez mieux comprendre comment fonctionnent réellement les contrats intelligents Move et comment relier en toute sécurité les systèmes hors chaîne on-chain ↔.

Et si vous déboguez des octets BCS sur Sui Explorer (comme celui ci-dessous) :

Encodage BCS La sérialisation canonique binaire, ou BCS, est un format de sérialisation développé dans le contexte de la blockchain Diem et est désormais largement utilisé dans la plupart des blockchains basées sur Move (Sui, Starcoin, Aptos, 0L). Le BCS n'est pas seulement utilisé dans la machine virtuelle Move, mais également dans le codage des transactions et des événements, comme la sérialisation des transactions avant la signature ou l'analyse des données d'événements.

Il est essentiel de connaître le fonctionnement de BCS si vous souhaitez comprendre le fonctionnement de Move à un niveau plus approfondi et devenir un expert de Move. Allons-y.

Spécifications et propriétés du BCS Il convient de garder à l'esprit certaines propriétés de haut niveau du codage BCS au cours de la suite de la leçon :

Le BCS est un format de sérialisation de données dans lequel les octets de sortie résultants ne contiennent aucune information de type ; de ce fait, la partie recevant les octets codés devra savoir comment désérialiser les données

Il n'y a pas de structures dans BCS (puisqu'il n'y a pas de types) ; la structure définit simplement l'ordre dans lequel les champs sont sérialisés

Les types de wrapper sont ignorés, donc OuterType et UnnestedType auront la même représentation BCS :

structure OuterType { propriétaire : InnerType } structure innerType { adresse : adresse } structure UnnestedType { adresse : adresse } Les types contenant les champs de type générique peuvent être analysés jusqu'au premier champ de type générique. Il est donc recommandé de placer le ou les champs de type générique en dernier s'il s'agit d'un type personnalisé qui sera utilisé/supprimé.

la structure BCSobject a été déposée, copiez { identifiant : identifiant, propriétaire : adresse, méta : métadonnées, générique : T } Dans cet exemple, nous pouvons tout désérialiser jusqu'au champ méta.

Les types primitifs tels que les entiers non signés sont codés au format Little Endian

Le vecteur est sérialisé sous la forme d'une longueur ULEB128 (avec une longueur maximale allant jusqu'à u32) suivie du contenu du vecteur.

La spécification BCS complète se trouve dans le référentiel BCS.

Utilisation de la bibliothèque JavaScript @mysten /bcs Installation La bibliothèque que vous devrez installer pour cette partie est la bibliothèque @mysten /bcs. Vous pouvez l'installer en saisissant dans le répertoire racine d'un projet de nœud :

npm dans @mysten /bcs Exemple de base Utilisons d'abord la bibliothèque JavaScript pour sérialiser et désérialiser certains types de données simples :

import {BCS, GetSuiMoveConfig} depuis « @mysten /bcs » ;

//initialise le sérialiseur avec les configurations Sui Move par défaut const bcs = nouveau BCS (getSuiMoveConfig ()) ;

//Définition de certains types de données de test entier constant = 10 ; tableau const = [1, 2, 3, 4] ; const string = « chaîne de test »

//utilise bcs.ser () pour sérialiser les données const ser_integer = bcs.ser (BCS.U16, entier) ; const ser_array = bcs.ser (« vecteur », tableau) ; const ser_string = bcs.ser (BCS.STRING, chaîne de caractères) ;

//utilisation de bcs.de () pour désérialiser les données const de_integer = bcs.de (BCS.U16, SER_Integer.toBytes ()) ; const de_array = bcs.de (« vecteur », SER_Array.toBytes ()) ; const de_string = bcs.de (BCS.STRING, SER_STRING.tobytes ()) ; Nous pouvons initialiser l'instance du sérialiseur avec le paramètre par défaut intégré pour Sui Move en utilisant la syntaxe ci-dessus, new BCS (getSuiMoveConfig ()).

Il existe des ENUM intégrés qui peuvent être utilisés pour les types Sui Move tels que BCS.U16, BCS.STRING, etc. Pour les types génériques, il peut être défini en utilisant la même syntaxe que dans Sui Move, comme vector dans l'exemple ci-dessus.

Examinons de plus près les champs sérialisés et désérialisés :

Les entiers sont des hexadécimaux de petite taille

0a00 10

le premier élément d'un vecteur indique la longueur totale,

alors c'est juste les éléments du vecteur

0401020304 1, 2, 3, 4

les chaînes ne sont que des vecteurs de u8, le premier élément étant égal à la longueur de la chaîne

0b7465737420737472696e67 chaîne de test Type d'enregistrement Nous pouvons enregistrer les types personnalisés sur lesquels nous allons travailler en utilisant la syntaxe suivante :

import {BCS, GetSuiMoveConfig} depuis « @mysten /bcs » ; const bcs = nouveau BCS (getSuiMoveConfig ()) ;

//Enregistrement du type de métadonnées BCS.RegisterStructType (« Métadonnées », { nom : BCS.STRING, }) ;

//Idem pour l'objet principal que nous avons l'intention de lire BCS.RegisterStructType (« BCSobject », { //BCS.ADDRESS est utilisé pour les types d'ID ainsi que pour les types d'adresses identifiant : BCS.ADDRESS, propriétaire : BCS.ADDRESS, meta : « Métadonnées », }) ; Utilisation de BCS dans Sui Smart Contracts Continuons notre exemple ci-dessus avec les structures.

Définition de la structure Nous commençons par les définitions de structure correspondantes dans le contrat Sui Move.

{ //.. struct Les métadonnées ont été supprimées, copiez { nom : std : :ascii : :String }

la structure BCSobject a été déposée, copiez { identifiant : identifiant, propriétaire : adresse, méta : Métadonnées } //.. } Désérialisation Écrivons maintenant la fonction permettant de désérialiser un objet dans un contrat Sui.

public fun object_from_bytes (bcs_bytes : vecteur) : BCSobject {

//Initialise l'instance bcs bytes let bcs = bcs : :new (bcs_bytes) ;

//Utilise peel_*des fonctions pour extraire les valeurs des octets sérialisés. //L'ordre doit être le même que celui que nous avons utilisé pour la sérialisation ! let (identifiant, propriétaire, méta) = ( bcs : :peel_address (&mut bcs), bcs : :peel_address (&mut bcs), bcs : :peel_vec_u8 (&mut bcs) ) ; //Compresse une structure BCSobject avec les résultats de la sérialisation BCSobject {id : object : :id_from_address (id), propriétaire, méta : Metadata {name : std : :ascii : :string (meta)}}} Les différentes méthodes peel_* du module Sui Frame bcs sont utilisées pour « extraire » chaque champ individuel des octets sérialisés BCS. Notez que l'ordre dans lequel nous décorons les champs doit être exactement le même que celui des champs dans la définition de la structure.

Quiz : Pourquoi les résultats des deux premiers appels peel_address sur le même objet bcs ne sont-ils pas les mêmes ?

Notez également comment nous convertissons les types d'adresse en identifiant et de vecteur en <8>std : :ascii : :string avec des fonctions d'assistance.

Quiz : Que se passerait-il si BSCobject avait un type d'UID au lieu d'un type d'ID ?

Exemple Ser/De complet Trouvez l'intégralité des exemples de codes JavaScript et Sui Move dans le dossier example_projects.

Tout d'abord, nous sérialisons un objet de test à l'aide du programme JavaScript :

//Nous construisons un objet de test à sérialiser, notez que nous pouvons spécifier le format de la sortie en hexadécimal let _bytes = bcs .ser (« BCSobject », { identifiant : « 0x0000000000000000000000000000000000000000000000000005", propriétaire : « 0x000000000000000000000000000000000000000000000000000a », meta : {nom : « aaa"} }) .toString (« hexadécimal ») ; Nous voulons que la sortie du graveur BCS soit au format hexadécimal cette fois, ce qui peut être spécifié comme ci-dessus.

Fixez la chaîne hexadécimale du résultat de la sérialisation avec le préfixe 0x et exportez-la vers une variable d'environnement :

export Object_HexString=0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A03616161 Nous pouvons maintenant soit exécuter les tests unitaires Move associés pour vérifier leur exactitude :

test de mouvement de costume Vous devriez voir ceci dans la console :

BÂTIMENT bcs_move Exécution de tests unitaires avec Move [PASS] 0x0 : :bcs_object : :test_désérialisation Résultat du test : OK. Nombre total de tests : 1 ; réussis : 1 ; échec : 0 Ou nous pouvons publier le module (et exporter le PACKAGE_ID) et appeler la méthode emit_object en utilisant la chaîne hexagonale sérialisée BCS ci-dessus :

appel client sui --function emit_object --module bcs_object --package $PACKAGE_ID --args $OBJECT_HEXSTRING Nous pouvons ensuite consulter l'onglet Événements de la transaction sur le Sui Explorer pour voir que nous avons émis le BCSObject correctement désérialisé :

  • Sui
  • SDKs and Developer Tools
2
Partager
Commentaires
.
harry phan.
May 30 2025, 17:12

Qu'est-ce que little-endian et big-endian ?

Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.

610Publications1335Réponses
Sui.X.Peera.

Gagne ta part de 1000 Sui

Gagne des points de réputation et obtiens des récompenses pour avoir aidé la communauté Sui à se développer.

Campagne de RécompensesJuillet