# Wire Format Overview This section documents the serialisation pipeline that transforms application-level data structures into encrypted bytes on the wire. Every byte exchanged between quicnprotochat clients and the server passes through this pipeline, so understanding it is prerequisite to reading the protocol deep dives or the server/client source code. --- ## Serialisation pipeline Data flows through three stages on the send path. The receive path reverses the order. ```text Stage 1 Stage 2 Stage 3 -------- -------- -------- Application Cap'n Proto Transport data serialisation encryption RPC call capnp::serialize QUIC/TLS 1.3 (zero-copy bytes) | | | v v v Rust structs Canonical byte Encrypted & method representation ciphertext invocations (no deserialization on the wire needed on receive) ``` ### Stage 1: Application creates a message or RPC call At the application layer, the client or server constructs a typed Cap'n Proto message. In the legacy Envelope path (M1), this means building an `Envelope` struct with a `MsgType` discriminant, group ID, sender ID, and opaque payload. In the current NodeService path (M3+), this means invoking a Cap'n Proto RPC method such as `enqueue()` or `fetchKeyPackage()`. - **Envelope** (legacy): see [Envelope Schema](envelope-schema.md) - **NodeService** (current): see [NodeService Schema](node-service-schema.md) - **AuthenticationService** (standalone): see [Auth Schema](auth-schema.md) - **DeliveryService** (standalone): see [Delivery Schema](delivery-schema.md) ### Stage 2: Cap'n Proto serialises to bytes Cap'n Proto converts the in-memory message to its canonical wire representation. This is a **zero-copy** format: the byte layout in memory is identical to the byte layout on the wire. No serialisation or deserialisation pass is required; readers can traverse the bytes in-place using pointer arithmetic. The wire representation consists of: 1. A **segment table** -- a list of segment sizes encoded as little-endian 32-bit integers. 2. One or more **segments** -- contiguous runs of 8-byte aligned words containing struct data, list data, and far pointers. Cap'n Proto's canonical form is deterministic for a given message, which makes it suitable for signing: two implementations that build the same logical message will produce identical bytes. ### Stage 3: Transport encryption The serialised bytes are encrypted by the QUIC/TLS 1.3 transport layer. The QUIC transport uses native QUIC stream framing, which provides its own length delimitation. Cap'n Proto RPC over QUIC relies on the `capnp-rpc` crate's built-in stream adapter. | Transport | Encryption | Authentication | |---|---|---| | **QUIC + TLS 1.3** | AES-128-GCM or ChaCha20-Poly1305 (negotiated by TLS) | Server cert (rustls/quinn) | The transport layer treats the payload as opaque bytes. It does not inspect or interpret the Cap'n Proto content. This clean separation means the serialisation format can evolve independently of the transport. --- ## Schema index The Cap'n Proto schemas that define the wire-level messages are documented on dedicated pages: | Schema File | Documentation Page | Purpose | |---|---|---| | `schemas/envelope.capnp` | [Envelope Schema](envelope-schema.md) | Legacy message envelope (M1) | | `schemas/auth.capnp` | [Auth Schema](auth-schema.md) | Authentication Service RPC interface | | `schemas/delivery.capnp` | [Delivery Schema](delivery-schema.md) | Delivery Service RPC interface | | `schemas/node.capnp` | [NodeService Schema](node-service-schema.md) | Unified node RPC (current) | --- ## Further reading - [Architecture Overview](../architecture/overview.md) -- system-level view of how services compose - [Protocol Layers Overview](../protocol-layers/overview.md) -- how transport, framing, and E2E encryption stack - [ADR-002: Cap'n Proto over MessagePack](../design-rationale/adr-002-capnproto.md) -- why Cap'n Proto was chosen