Binary Encoding
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.
#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 byte2 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 |
#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 bytesFixed 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