Working with Bencodex

Working with Bencodex

Bencodex is a serialization/deserialization format that Libplanet-based games use for serializing the game transactions, actions and more.

Why Bencodex

This section is a summary of the README of Bencodex repository.

Bencodex makes sure there is only one valid way to represent any value. This property makes checking equality between two values trivial; there is no way to have multiple same Bencodex values with different representations.

Data Types

The data types used in Bencodex are similar to what you would find in a normal JSON, with some differences like:

  • byte strings
  • replaced numbers with integers ā€“ meaning no floating numbers can be stored

This also means that as long as your JSON data contains no decimal points, you can convert them to Bencodex without a loss of data.

The complex data can be stored in arrays and dictionaries (corresponding to objects in JSON). Unlike JSON, you can choose to have byte string as a key.

Transmit over Text-based Channels

Bencodex is a binary-encoded format, so the data is usually encoded as hexadecimal when packed inside JSON or GraphQL. The 0x prefix is not used.

Youā€™ll typically see this when working with GraphQL APIs of Nine Chronicles.

Bindings

C#

The C# bindings provide basic Encode and Decode methods for working with Bencodex data.

TODO: Fill this section.

JavaScript/TypeScript

Thereā€™s a third-party implementation for Bencodex which is also used within some of Planetariumā€™s products, such as the Nine Chronicles launcher.

To get a copy, you can install it on npm:

npm install bencodex

The API is fairly simple: it has encode for serializing the value into Bencodex or decode for vice-versa.

Note that the library decodes dictionaries into Map. You can use them via its methods or convert them to plain JavaScript object using Object.fromEntries.

1 Like

can you please give some examples about this?

1 Like

Well, Iā€™m curious too. Mixed key types in the same dictionary are technically possible and I tested it with javascript implementation.
Example 1:

decode(Buffer.from(ā€˜d3:cowu3:moou3:cow4:eggseā€™))
Map(2) { <Buffer 63 6f 77> => ā€˜mooā€™, ā€˜cowā€™ => <Buffer 65 67 67 73> }

I think what @Basix might tried to say was, you canā€™t mix byte-string based keys and ā€œNON-UNICODEā€ based string (which is actually byte-string), as theyā€™re indistinguishable in original bencodex format.

From that aside, I generally disencourage mixing the key type when using a dictionary, I mean you ā€˜canā€™ generate key type mixed bencodex string as d3:cowu3:moou3:cow4:eggse has 3:cow byte-string key and u3:cow Unicode-string key but most of the libraries will have a hard time when deserializing them and typing it as Dictionary<KeyType, ValueType>.

1 Like

Turns out it was my misinterpretation of the documentation :sweat:

1 Like