Skip to content

Binary Encoding

The XE network uses a deterministic binary encoding format for blocks and votes. This encoding is critical for hashing, signing, and network serialization -- all implementations must produce byte-identical output for the same logical data.

Version 2 is current

The encoding format described here is version 2 (0x02). Older formats are not supported.

Block canonical encoding

The canonical encoding is used for computing block hashes and signatures. It excludes the PoW nonce -- only the content that the account holder signs is included.

Field layout

Offset  Size  Field
──────  ────  ─────
0       1     Version byte (0x02)
1       1     Type byte
2       8     Asset (left-aligned UTF-8, zero-padded to 8 bytes)
10      32    Account (hex-decoded to raw 32 bytes)
42      32    Previous (hex-decoded; genesis blocks use 32 zero bytes)
74      8     Balance (big-endian uint64)
82      8     Timestamp (big-endian int64)
90+     var   Type-specific tail (see below)
last    32    Representative (appended after type tail; 32 zero bytes if empty)

Type bytes

Type Byte Description
Send 0x01 Transfer funds to another account
Receive 0x02 Accept a pending send
Claim 0x03 Faucet claim (100 XUSD)
Lease 0x04 Request a compute lease
LeaseAccept 0x05 Provider accepts a lease
LeaseSettle 0x06 Settle a completed lease
MultisigOpen 0x08 Open a multisig account
MultisigUpdate 0x09 Rotate a multisig keyset

Type-specific tails

Each block type appends additional fields after the common header:

Send

Offset Size Field
90 32 Destination (hex-decoded)
122 8 Amount (big-endian uint64)

Total canonical size: 162 bytes (130 + 32 representative)

Receive

Offset Size Field
90 32 Source hash (hex-decoded)

Total canonical size: 154 bytes (122 + 32 representative)

Claim

No additional fields.

Total canonical size: 122 bytes (90 + 32 representative)

Lease

Offset Size Field
90 32 Destination / provider (hex-decoded)
122 8 Amount (big-endian uint64)
130 8 vCPUs (big-endian uint64)
138 8 Memory MB (big-endian uint64)
146 8 Disk GB (big-endian uint64)
154 8 Duration seconds (big-endian uint64)
162 32 AccessPubKey (hex-decoded ed25519 public key; empty → 32 zero bytes)

Total canonical size: 226 bytes (90 base + 104 tail + 32 representative)

LeaseAccept

Offset Size Field
90 32 Source / lease hash (hex-decoded)
122 8 Amount (big-endian uint64)

Total canonical size: 162 bytes (130 + 32 representative)

LeaseSettle

Offset Size Field
90 32 Source / lease hash (hex-decoded)
122 8 Amount (big-endian uint64)

Total canonical size: 162 bytes (130 + 32 representative)

MultisigOpen / MultisigUpdate

Offset Size Field
90 4 Threshold (big-endian uint32)
94 4 Number of keys (big-endian uint32)
98 32×N Keys (sorted, hex-decoded, 32 bytes each)

Total canonical size: 130 + 32N bytes (90 header + 8 + 32N keyset + 32 representative)

Keys are sorted lexicographically before encoding. This ensures the same keyset always produces the same canonical encoding and thus the same derived address.

Full block encoding

The full block encoding appends the PoW nonce after the canonical bytes:

[ canonical bytes ] [ 8 bytes PoW nonce (little-endian uint64) ]

This is the format used for storage and network transmission. The MarshalBlock function produces this format, and UnmarshalBlock parses it.

Field encoding rules

Field Encoding
Hex strings (account, previous, hashes) Decoded to raw bytes (32 bytes each)
Asset Left-aligned UTF-8, zero-padded to exactly 8 bytes
Previous = "0" (genesis) 32 zero bytes
Balance, Amount Big-endian uint64
Timestamp Big-endian int64
PoW Nonce Little-endian uint64
Representative (empty) 32 zero bytes

Endianness

The PoW nonce uses little-endian encoding while all other numeric fields use big-endian. This is intentional and must be preserved across implementations.

Vote encoding

Votes are serialized for signing and network transmission:

Offset  Size  Field
──────  ────  ─────
0       1     Version byte (0x01)
1       32    Representative public key (hex-decoded)
33      32    Block hash (hex-decoded)
65      32    Conflict account (hex-decoded)
97      32    Conflict previous (hex-decoded; "0" → 32 zero bytes)
129     8     Timestamp (big-endian int64)
137     2     Signature length (big-endian uint16)
139     N     Signature bytes

Fixed portion: 139 bytes + variable signature length.

Functions

The encoding package exposes the following functions:

Function Description
MarshalBlockCanonical(block) Encode a block for hashing/signing (no PoW nonce)
MarshalBlock(block) Full encoding including PoW nonce trailer
UnmarshalBlock(data) Decode a full block from bytes
EncodeVote(vote) Serialize a vote for signing/transmission
DecodeVote(data) Deserialize a vote from bytes

See also