Skip to content

Block Lattice

The block lattice is the data structure at the heart of XE. Unlike traditional blockchains where all transactions are ordered into a single global chain, the block lattice gives every account its own chain. The set of all account chains, linked together by cross-chain references, forms a directed acyclic graph (DAG).

How it works

Account chains

Every account address corresponds to a chain of blocks. Each block's Previous field points to the hash of the preceding block on the same chain, forming a linked list. The first block on any chain has Previous set to "0" (the open block).

Account A          Account B          Account C
┌──────────┐       ┌──────────┐       ┌──────────┐
│ claim    │       │ receive  │       │ claim    │
│ prev: 0  │       │ prev: 0  │       │ prev: 0  │
│ bal: 1   │       │ bal: 5   │       │ bal: 1   │
│ hash: a1 │       │ hash: b1 │       │ hash: c1 │
└────┬─────┘       └────┬─────┘       └────┬─────┘
     │                  │                  │
┌────▼─────┐       ┌────▼─────┐       ┌────▼─────┐
│ claim    │       │ send     │       │ receive  │
│ prev: a1 │       │ prev: b1 │──┐    │ prev: c1 │
│ bal: 2   │       │ bal: 2   │  │    │ bal: 4   │◄──┐
│ hash: a2 │       │ dest: C  │  │    │ src: b2  │───┘
└────┬─────┘       │ amt: 3   │  │    │ hash: c2 │
     │             │ hash: b2 │──┘    └────┬─────┘
┌────▼─────┐       └────┬─────┘            │
│ send     │            │             ┌────▼─────┐
│ prev: a2 │       ┌────▼─────┐      │ send     │
│ bal: 1   │       │ receive  │      │ prev: c2 │
│ dest: B  │       │ prev: b2 │      │ bal: 2   │
│ amt: 1   │       │ bal: 3   │      │ dest: A  │
│ hash: a3 │       │ src: a3  │◄──── │ amt: 2   │
└──────────┘       │ hash: b3 │      │ hash: c3 │
                   └──────────┘      └──────────┘

Transfers require two blocks:

  1. A send block on the sender's chain debits the sender. It specifies the destination account and amount. This creates a pending send.
  2. A receive block on the recipient's chain credits the recipient. Its Source field references the hash of the send block, consuming the pending send.

These cross-chain references are what turn the collection of independent chains into a DAG. A send block points forward to a destination account; a receive block points back to the source send block.

Asynchronous settlement

The sender and receiver do not need to be online at the same time. The send creates a pending entry that persists until the recipient creates the corresponding receive block. This is fundamentally different from traditional blockchains where both sides of a transfer are recorded in a single transaction.

Frontier

The frontier of an account is the hash of the latest block on its chain. Frontiers are the primary mechanism for sync -- nodes exchange frontier maps to detect which accounts have blocks the other node hasn't seen.

Properties

No contention between accounts

Because each account has its own chain, two transactions involving different accounts can be processed simultaneously. There is no lock on a global chain, no block interval to wait for, and no ordering dependency between unrelated transactions.

Parallel processing

Nodes validate blocks for different accounts in parallel using per-account locks. A send to account A and a send to account B are processed concurrently with no synchronization between them.

Instant finality for non-conflicting transactions

When there is no equivocation (i.e., no two blocks compete for the same position on a chain), a block is confirmed the moment it passes validation. There is no need to wait for additional confirmations.

Compact representation

Each block contains only one operation (one send, one receive, one claim, etc.). Blocks are small -- the canonical binary encoding ranges from 122 bytes (claim) to 194 bytes (lease) plus the 8-byte PoW nonce.

Conflict resolution

A conflict (equivocation) occurs when an account publishes two or more blocks with the same Previous hash -- essentially trying to fork their own chain. This is the only scenario that requires consensus.

When a conflict is detected:

  1. The conflicting blocks are placed in staging (not added to the main chain).
  2. The node's VoteManager automatically casts a vote for one of the conflicting blocks, weighted by the account's delegated XE balance.
  3. Votes are broadcast via the vote gossip topic.
  4. The QuorumManager tallies votes. When one block accumulates 67% of total delegated XE weight, it is confirmed and the others are rejected.

See Consensus for full details on delegation, voting, and quorum.

Relationship to Nano

XE's block lattice is directly inspired by Nano's block-lattice architecture. The key differences are:

  • Dual assets -- XE tracks two assets (XE and XUSD) per account, not just one balance.
  • Additional block types -- lease, lease_accept, and lease_settle blocks extend the lattice for compute leasing.
  • State chain -- a separate governance layer for network parameter updates.
  • Proof of work -- XE uses blake2b PoW as anti-spam rather than Nano's receive-prioritization approach.
  • Representatives -- voting weight is derived from XE balances only; XUSD does not confer voting power.