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:
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¶
- Cryptography -- hashing and signing over canonical bytes
- Proof of Work -- PoW computed over the block hash
- Block Types -- logical structure of each block type