DSON encoding

Introduction

Radix encoders provide both a binary encoding (known as DSON) and a JSON format. Encodings include a number of primitives and two container types.

Radix Binary Encoding (DSON)

DSON encoding is a subset of the IETF's Concise Binary Object Representation (CBOR), and should be consumable using any CBOR-compliant library. CBOR is documented in IETF RFC-7049.

Care should be taken when producing CBOR output to only utilise the features documented here to ensure maximum interoperability between Radix clients and servers.

Primitives

Supported primitives are:

Type

Description

bool_false

The boolean "false" value

bool_true

The boolean "true" value

number

a signed 64-bit numeric value, -263 ≤ x ≤ 263-1

EUID

a 128-bit identifier

address

a checksummed address within a specific Universe

hash

a SHA-256 hash value

bytes

an array of bytes of unspecified content

string

an array of UTF-8 encoded unicode characters

Containers

The two supported container types are:

  • A non-homogeneous sequence of values

  • A map of names to non-homogeneous values

CBOR Major Types

The following CBOR encoding major types are used for Radix encoding. All CBOR major type encodings are defined in RFC-7049 section 2, and the following table will need to be read in conjunction with that document.

The "0x" prefix is used to denote a number expressed in hexadecimal, and "0b" prefix to denote a number expressed in binary.

Radix Type

CBOR major type

Additional information

Additional encoding

Example encodings

bool_false

0b111 (7)

0b1_0100 (20)

None

bool_false = 0b1111_0100 (0xF4)

bool_true

0b111 (7)

0b1_0101 (21)

None

bool true = 0b1111_0101 (0xF5)

number (positive)

0b000 (0)

most compact encoding

None

10 = 0b0000_1010 (0x0A) 128 = 0b0001_1000 0b1000_0000 (0x14 0x80) 256 = 0b0001_1001 0b0000_0001 0b0000_0000 (0x15 0x01 0x00) 500 = 0b0001_1001 0b0000_0001 0b1111_0100 (0x15 0x01 0xF4)

number (negative)

0b001 (1)

most compact encoding

None

-1 = 0b0010_0000 (0x20) -500 = 0b0011_1001 0b0000_0001 0b1111_0011 = (0x39 0x01 0xF3)

bytes

0b010 (2)

most compact encoding

Leading byte 0x01

0x89 0xAB 0xCD 0xEF = 0b0100_0101 0x01 0x89 0xAB 0xCD 0xEF

EUID

0b010 (2)

0b0_1001

Leading byte 0x02

0x01 0x02 … 0x07 0x08 = 0b0100_1001 0x02 0x01 0x02 … 0x07 0x08

hash

0b010 (2)

0b1_0100 0b0010_0001

Leading byte 0x03

0x89 0xAB 0xCD 0xEF … = 0b0101_0100 0x21 0x03 0x89 0xAB 0xCD 0xEF …

address

0b010 (2)

0b1_1000 0b0010_0111

Leading byte 0x04

For universe magic 0x02 and public key 0x03 0x00 0x01 0x02 0x03 … 0x1F:

0b0101_1000 0x27 0x04 0x02 0x03 0x00 0x01 0x02 … 0x1E 0x1F 0x17 0x53 0x41 0xA9

uint256

0b010 (2)

0b1_1000 0b0010_0001

Leading byte 0x05

0x01 0x02 … 0x1E 0x1F = 0b0101_1000 0x21 0x05 0x00 0x01 0x02 … 0x1E 0x1F

rri

0b010 (2)

most compact encoding

Leading byte 0x06

"/radix" = 0b0101_0111 0x06 0x2f 0x72 0x61 0x64 0x69 0x78

string

0b011 (3)

most compact encoding

None

"Radix" = 0b0110_0101 0x52 0x61 0x64 0x69 0x74

sequence

0b100 (4)

most compact encoding

None

[ 1, 2, 3, 4 ] = 0b1000_0100 0x01 0x02 0x03 0x04 Sequence of four numbers 1, 2, 3 and 4. [ 0, 1, … 126, 127 ] = 0b1001_0100 0x80 0x00 0x01 … 0x14 0x7E 0x14 0x7F Sequence of numbers from 0 to 127

map

0b101 (5)

streaming encoding

Note that this is a different encoding to that described in RFC-7049, section 3.9.

None

{ "a":1, "b":2 } = 0b1011_1111 0b0110_0001 0x61 0x01 0b0110_0001 0x62 0x02 0xFF Map with two keys, "a" and "b", mapping to numeric values 1 and 2 respectively

Notes

Note: CBOR provides several possible encodings for some items, particularly integers and lengths. Because DSON encoded data is used to calculate hashes, it is crucial that all libraries encode data in a consistent way, and we, therefore, require encoders to utilise the most compact encoding possible where several options are possible, except for maps, where the streaming encoding is always used.

Note: The "bytes", "EUID" and "hash" primitives are all encoded using the CBOR "byte string" major type. An additional initial byte is encoded in the payload to allow readers to distinguish between these types without requiring a schema.

Note: While it is possible to encode arbitrary types for keys in a map, only string keys are supported. Keys are output in lexicographical order to ensure consistent hashing — note that this is a different sort order to that described in RFC-7049, section 3.9.

Note: DSON decoders may elect to interpret, ignore or fail for CBOR encodings not included above, including unused CBOR major type 6 and unused elements of CBOR major type 7.

Note: DSON encoders must ensure that only CBOR encodings included above are used.

Javascript Representation (JSON)

Radix client libraries use JSON encoded data for exchange between client and server. This section covers how DSON encoded values are represented in JSON.

Note: most clients will need to be able to serialize into DSON encoding in order to correctly calculate hashes.

Type

JSON value prefix

Value encoding

boolean_true

none

Unquoted literal text "true"

boolean_false

none

Unquoted literal text "false"

number

none

Sequence of decimal digits with a possible '-' sign

address

":adr:"

Base58 encoded string

bytes

":byt:"

Base64 encoded string

EUID

":uid:"

Sequence of hexadecimal digits

hash

":hsh:"

Sequence of hexadecimal digits

rri

":rri:"

UTF-8 encoded unicode characters representing a URI

string

":str:"

UTF-8 encoded unicode characters

uint256

":u20:"

Sequence of decimal digits

sequence

none

Represented as a JSON array

map

none

Represented as a JSON object