Block Lattice
How XE's per-account blockchain works
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
┌──────────┐ ┌──────────┐ ┌──────────┐
│ receive │ │ receive │ │ receive │
│ prev: 0 │ │ prev: 0 │ │ prev: 0 │
│ bal: 1 │ │ bal: 5 │ │ bal: 1 │
│ hash: a1 │ │ hash: b1 │ │ hash: c1 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
┌────▼─────┐ ┌────▼─────┐ ┌────▼─────┐
│ receive │ │ 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 │
└──────────┘ └──────────┘Cross-chain links
Transfers require two blocks:
- A send block on the sender's chain debits the sender. It specifies the destination account and amount. This creates a pending send.
- A receive block on the recipient's chain credits the recipient. Its
Sourcefield 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.
[!INFO] 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.
Finalization runs on every position
Every chain position runs a finalization election, not just the ones that fork. Where there is no equivocation there is a single candidate, so the election has nothing to arbitrate and converges without a competing branch — but a block becomes irreversible only once representatives have final-voted it. This is why an account's spendable balance is reported separately from its live balance: spendable counts only finalized inflows.
Compact representation
Each block contains only one operation (one send, one receive, one mint, etc.). Blocks are small -- the canonical binary encoding starts at 122 bytes (a genesis block) and reaches 226 bytes for a lease, plus the 8-byte PoW nonce in the wire encoding. A send or burn grows by its optional memo (up to 64 bytes) and a multisig block by its keyset size.
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 scenario the election has to arbitrate.
When a conflict is detected:
- The conflicting blocks are placed in staging (not added to the main chain).
- Representatives cast a converge vote for their preferred candidate -- the lowest hash among the candidates they have seen. Converge votes are mutable: a representative may revote as it learns of more siblings. Weight comes from delegated XE balance.
- Votes are broadcast via the vote gossip topic.
- Once a candidate holds a visible supermajority of converge weight, a representative writes a durable write-once commit-lock and casts an irrevocable final vote for the locked hash.
- The QuorumManager tallies final votes. A block finalizes when 67% of total delegated XE weight has final-voted it; the losing siblings are rejected and their side effects unwound. A long-open election has a lower fallback bar (a strict majority of final-voted weight on the lowest-hash candidate) so a position does not stall when a third of the weight is offline — see Quorum.
The commit-lock makes a representative structurally unable to final-vote two hashes at the same position, so adversarial timing or a restart can delay finalization but never produce two finalized siblings.
See Consensus for full details on delegation, voting, and quorum.
How XE Extends the Model
A plain block lattice moves a single balance between accounts. XE builds on that foundation:
- Dual assets -- XE tracks two assets (XE and XUSD) per account, not just one balance.
- Compute leasing as first-class blocks -- the lease lifecycle (lease, lease_accept, lease_settle, lease_cancel, lease_force_settle) rides on the lattice itself rather than a contract layer above it, alongside mint, burn, and multisig blocks. See Block Types.
- State chain -- a separate governance layer for network parameter updates.
- Proof of work -- blake2b PoW on every block, used purely as an anti-spam cost.
- Representatives -- voting weight is derived from XE balances only; XUSD does not confer voting power.