ZAP (Zero-copy Allocation-free Protocol) is Lux Network's binary wire protocol for node-to-node communication. It replaces the legacy Protobuf-based protocol with a fixed-layout binary format that achieves sub-microsecond serialization through zero-copy parsing and arena-based allocation. All consensus messages, block propagation, and peer management use ZAP framing.
+--------+--------+----------+---------+----------+
| Magic | MsgType| Length | Payload | Checksum |
| 2B | 1B | 4B (BE) | variable| 4B CRC32 |
+--------+--------+----------+---------+----------+
0x5A50 ("ZP") -- identifies ZAP frames on the wireMsgType || Length || PayloadHandshake | 0x01 | bidirectional | Version, network ID, node ID, BLS key |Ping | 0x02 | bidirectional | Keepalive with uptimes |Pong | 0x03 | bidirectional | Ping response |PushBlock | 0x10 | push | New block with QC |PullBlock | 0x11 | request | Request block by ID |BlockResponse | 0x12 | response | Block data |PushTx | 0x20 | push | Transaction gossip |Consensus | 0x30 | bidirectional | Consensus votes, proposals |WarpMsg | 0x40 | push | Cross-chain Warp message relay |StateSync | 0x50 | bidirectional | State sync chunks (LP-024) |Payloads use fixed-offset layouts. Fields are packed in declaration order with explicit alignment:
uint64 / int64: 8 bytes, big-endian[32]byte: 32 bytes, no prefix[]byte: 4-byte length prefix + databool: 1 byte (0x00 or 0x01)No reflection, no field tags, no schema evolution within a version. Protocol changes require a version bump in the Handshake message.
The receiver maps the payload buffer directly to a typed struct. No intermediate allocations:
1. Validate checksum (CRC32-C, hardware-accelerated on x86/ARM)
2. Bounds-check field offsets against Length
3. Return a view struct referencing the original buffer
The buffer is owned by an arena allocator recycled per connection. Typical parse time: 200-400 nanoseconds for a full block message.
PushBlock and StateSync (negotiated in handshake)ZAP supports optional TLS 1.3 via NodeConfig.TLS. When enabled, the TLS layer wraps the underlying TCP connection before ZAP framing begins.
Go 1.26 includes X25519MLKEM768 (ML-KEM-768 + X25519 hybrid) in the default supported curves list. Three PQ curves are available:
X25519MLKEM768 is the default first curve. No explicit configuration needed -- Go's crypto/tls negotiates it automatically with any peer running Go 1.26+.
TLS operates beneath the ZAP framing layer. The ZAP deserializer reads from io.Reader, which is satisfied by tls.Conn identically to a raw net.Conn. The zero-copy parsing path (arena allocation, direct buffer mapping) is unchanged. TLS encryption/decryption happens at the OS read/write boundary, not in the serialization path.
1. No schema evolution: prevents deserialization confusion attacks. Peers must agree on protocol version at handshake.
2. CRC32-C: detects corruption, not tampering. TLS provides authentication and integrity.
3. 8 MB payload limit: bounds memory allocation per message. Blocks exceeding this are split across multiple StateSync chunks.
github.com/luxfi/node/network/zap/ |github.com/luxfi/node/network/peer/ |Copyright (C) 2024-2026, Lux Partners Limited. All rights reserved.
Licensed under the MIT License.