CAD036: Lattice Node
Overview
A Lattice Node is a networked server that participates in Data Lattice replication. Unlike full Convex Peers that implement Convergent Proof of Stake consensus for global state, Lattice Nodes focus exclusively on CRDT-based synchronisation of lattice values across a distributed network.
Lattice Nodes enable decentralised applications to share and replicate data without blockchain consensus overhead, while still benefiting from content-addressable storage, Merkle verification, and automatic conflict resolution through lattice merge semantics.
Motivation
The Data Lattice (CAD024) provides the theoretical foundation for decentralised data storage. However, applications need practical infrastructure to:
- Host and serve lattice data - Nodes that store and make data available
- Synchronise across networks - Automatic replication between distributed nodes
- Handle partial data - Recover missing data from peers during merges
- Propagate updates efficiently - Minimise bandwidth with delta encoding
- Detect divergence - Lightweight mechanisms to identify out-of-sync nodes
Lattice Nodes provide this infrastructure as a lightweight alternative to full blockchain peers, suitable for:
- Distributed file systems (DLFS - see CAD028)
- Content delivery networks
- Collaborative applications
- Federated data sharing
- Off-chain data for hybrid dApps
Specification
Node Architecture
A Lattice Node consists of the following logical components:
┌─────────────────────────────────────────────────────────────┐
│ Lattice Node │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Cursor │ │ Lattice │ │ Store │ │
│ │ (State) │ │ (Merge) │ │ (Persistence) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Network Server ││
│ │ • Message handling (PING, QUERY, VALUE, DATA_REQUEST) ││
│ │ • Peer connections ││
│ └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────── ──┤
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Update Propagator ││
│ │ • Delta broadcasting ││
│ │ • Root sync ││
│ │ • Novelty detection ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Cursor (State)
Each node maintains a cursor (see CAD035) pointing to its current lattice value.
The cursor MUST:
- Provide atomic read/write operations
- Support path-based access into nested structures
- Enable thread-safe concurrent updates
Lattice (Merge)
The lattice defines merge semantics for conflict resolution.
The lattice MUST:
- Satisfy CRDT properties (commutative, associative, idempotent)
- Provide a
zeroidentity value - Validate foreign values before merging via
checkForeign() - Support hierarchical path navigation to sub-lattices
Store (Persistence)
The store provides content-addressable storage for lattice values.
The store MUST:
- Support retrieval by cryptographic hash (SHA3-256)
- Track which data has been announced (for delta encoding)
- Handle persistence of Merkle tree structures
- Use the encoding format specified in CAD003
Commit Durability
A node's primary propagator commits synchronously. When an application calls sync(), the primary propagator runs announce, root persistence and broadcast on the caller's own thread, and the call returns only once the new root is durably persisted in the primary store. Persistence errors propagate to the caller rather than being swallowed, so a successful return is a durability guarantee. Any secondary propagators remain asynchronous.
To keep this guarantee consistent under concurrency, the propagator is the sole writer of the store's root pointer: snapshot and persist pipelines are serialised, so an older snapshot can never demote the root pointer after a newer snapshot's sync has already returned.
Network Protocol
Lattice Nodes communicate using a binary protocol. Messages use the encoding format specified in CAD003.
Message Framing
Messages are framed as:
- VLQ-encoded length prefix
- Message payload (encoded per CAD003)
Message Types
| Type ID | Name | Description |
|---|---|---|
| 5 | DATA_REQUEST | Request missing data cells |
| 12 | PING | Connectivity test |
| 14 | LATTICE_VALUE | Announce lattice value update |
| 15 | LATTICE_QUERY | Request lattice value at path |
PING (Type 12)
Connectivity test message.
Request format:
[:PING id]
id: Request identifier (any CVM value)
Response: Result message containing (id, "PONG")
Nodes MUST respond to PING messages with a Result containing the same ID.
LATTICE_QUERY (Type 15)
Request lattice value at a path.
Request format:
[:LQ id path]
id: Request identifier (for correlating response)path: Vector of keys specifying path into lattice (empty vector[]= root)
Response: Result message containing (id, value)
value: Lattice value at the requested path (encoded per CAD003)
Nodes MUST respond with the current value at the specified path, or an error Result if the path is invalid.
LATTICE_VALUE (Type 14)
Announce a lattice value update.
Message format:
[:LV path value]
path: Vector of keys specifying path (empty vector[]= root)value: New lattice value to merge (encoded per CAD003)
Messages MAY include delta-encoded data for bandwidth efficiency (see Delta Encoding below).
Upon receiving a LATTICE_VALUE message, nodes MUST:
- Extract the path from the message
- Validate the path against the lattice structure
- Validate the foreign value using
checkForeign() - Merge the value using lattice semantics
- Handle missing data by acquiring from peers (see Missing Data Recovery)
- Trigger propagation of merged changes
DATA_REQUEST (Type 5)
Request missing data cells by hash.
Request format:
[:DR id hash1 hash2 ...]
id: Request identifierhash1, hash2, ...: SHA3-256 hashes of missing data cells (32-byte blobs)
Response: Message containing requested cells
Nodes SHOULD respond with available data from their store. Unavailable cells SHOULD be encoded as nil values.
Value Encoding
All values exchanged between nodes MUST use the canonical encoding format specified in CAD003.
Key encoding properties:
- All CVM values have a unique canonical encoding
- Value ID = SHA3-256 hash of encoding
- Merkle tree structure enables incremental verification
- Multi-cell encoding supports complex nested values
Missing Data Recovery
Lattice values are Merkle trees that may reference data not yet available locally. Nodes MUST implement missing data recovery.
Speculative Merge Pattern
- Attempt merge with received value
- If merge fails due to missing data, capture the missing hash
- Acquire missing data from connected peers via DATA_REQUEST
- Retry merge (up to configurable limit)
- Commit merged value on success
Recommended parameters:
- Maximum retry attempts: 3
- Acquisition timeout per peer: 5 seconds
Data Acquisition Algorithm
function acquire(missingHash):
for each connectedPeer:
response = sendDataRequest(peer, missingHash)
if response contains data:
store data locally
return data
return null (acquisition failed)
Delta Encoding
To minimise bandwidth, nodes SHOULD implement delta encoding for LATTICE_VALUE messages.
Novelty Detection
Nodes track which cells have been "announced" to the store. When broadcasting:
- Walk the value's Merkle tree
- Collect cells not previously announced
- Mark collected cells as announced
- Encode only novel cells
Delta Message Format
LATTICE_VALUE messages include encoded message data:
- Standard encoding: Only the value's top cell
- Delta encoding: All novel cells in dependency order
Receivers reconstruct the full value by:
- Decoding received cells into local store
- Resolving the top cell's references
- Acquiring any still-missing data from peers
Update Propagation
Nodes SHOULD implement automatic propagation of updates to peers.