Skip to content

Protocol messages

Protocol message are not separately digitally signed due to the TLS transport and certificate authentication.

All protocol messages start with the same 4 byte sequence consisting of one byte for the type, and three bytes for the full byte length of the entire protocol message encoded in little-endian format. This allows the protocol to be easily framed within a stream.

Asynchronous

All client messages initiate an action, and all server messages are in response to client messages (NOTE: this MAY not apply to Mosaic extensions). Yet messaging is asychronous and both sides SHOULD be prepared to deal with a message sent at any time.

Servers SHOULD not send messages until they receive a message that requires a response.

If a server fails to receive a message from a client that does not have an open query or submission within a reasonable timeframe, it MAY close the connection.

If a client receives a server message that was not expected, it MUST ignore it and decide what to do next. In some cases, clients MAY close the connection because the service they were seeking failed. In other cases they MAY try something else. There is no provision for a client to alert a server of an error.

Messages

Every message starts with a one-byte type, shown below in the header of each type. Following this is the data of the message.

Initiator Message Type
Client Hello 0x10
Client Hello Auth 0x11
Client Get 0x1
Client Query 0x2
Client Subscribe 0x3
Client Unsubscribe 0x4
Client Submission 0x5
Client BLOB Get 0x8
Client BLOB Submission 0x7
Client DHT Lookup 0x6
Server Hello Ack 0x90
Server Closing 0xFE
Server Record 0x80
Server Locally Complete 0x81
Server Query Closed 0x82
Server Submission Result 0x83
Server BLOB Result 0x86
Server BLOB Submission Result 0x85
Server DHT Response 0x84
Either Unrecognized 0xF0

All messages share the following fields:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    |  T  |                 |         LENGTH        |
 8  +-----------------------------------------------+
  • [0:1] - The message Type
  • [4:8] - The byte length of this message, in little-endian format

The 4-byte length limits the maximum message to 4 GB.


Client Messages

Hello

NOTE: WebSockets sends HELLO information out of band and does not utilize this message.

This is the initial message sent from the client to the server. It specifies the highest Mosaic version that the client supports, as well as the applications that the client is requesting to utilize.

It has the following format:


    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x10|     0     | MV  |        LENGTH         |
 8  +-----------------------------------------------+
    | APP_ID                | ...                   |
    +-----------------------------------------------+
  • [0:1] - The type 0x10
  • [1:3] - Zeroed
  • [3:4] - MOSAIC_MAJOR_VERSION - The highest Mosaic major version number that the client supports, in little-endian format.
  • [4:8] - The byte length of this message, in little-endian format.
  • [8:] - A sequence of 32-bit Application IDs that the client wishes to use, in little-endian format

This is a client initiated message. Servers are expected to reply with Hello Ack.

Hello Auth

Only WebSockets utilizes this message. QUIC and TCP handle authentication at the TLS layer.

TBD

Get

This is a query for specific records.

It has the following format:


    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x1 |  0  | QUERY_ID  |        LENGTH         |
 8  +-----------------------------------------------+
    | Mixed IDs or ADDRs, each one 48 bytes long... |
    | ...                                           |
    +-----------------------------------------------+
  • [0:1] - The type 0x1
  • [1:2] - Zeroed
  • [2:4] - QUERY_ID, two bytes which SHOULD be made up by the client and used to associate returned Record responses to this request.
  • [4:8] - The byte length of this message, in little-endian format.
  • [8:] - A sequence of mixed IDs and ADDRs. Note that ADDRs start with a 1 bit, whereas IDs start with a 0 bit, and both of them are 48 bytes long.

This is a client initiated message. Servers are expected to reply with:

  • A series of zero or more Record messages representing all the matched records on the server, followed by a Query Closed message.

Query

This is a query for records that closes once served.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x2 |  0  | QUERY_ID  |        LENGTH         |
 8  +-----------------------------------------------+
    |   LIMIT   |                0                  |
16  +-----------------------------------------------+
    |  FILTER...                                    |
    +-----------------------------------------------+
  • [0:1] - The type 0x2
  • [1:2] - Zeroed
  • [2:4] - QUERY_ID two bytes which SHOULD be made up by the client and used to associate returned Record responses to this request.
  • [4:8] - The byte length of this message, in little-endian format.
  • [8:10] - LIMIT, an unsigned integer in little-endian format, specifies the maximum number of responses that the client wishes to receive. A value of 0 indicates unlimited.
  • [10:16] - Zeroed
  • [16:] - The FILTER, see Filter.

This is a client initiated message. Servers are expected to reply with:

  • a series of zero or more Record messages representing all the matching records on the server initially, followed by a Query Closed message.

Queries MUST return results in anti-chronological order, from most recent backwards.

Subscribe

This is a query for records that is kept open after the initial records are served so that newly arriving records that match can be sent to the client immediately.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x3 |  0  |  QUERY_ID |       LENGTH          |
 8  +-----------------------------------------------+
    |   LIMIT   |                0                  |
16  +-----------------------------------------------+
    | FILTER ...                                    |
    +-----------------------------------------------+
  • [0:1] - The type 0x3
  • [1:2] - Zeroed
  • [2:4] - QUERY_ID, two bytes which SHOULD be made up by the client and used to associate returned Record responses to this request.
  • [4:8] - The byte length of this message, in little-endian format.
  • [8:10] - LIMIT, an unsigned integer in little-endian format, specifies the maximum number of responses that the client wishes to receive. A value of 0 indicates unlimited.
  • [10:16] - Zeroed
  • [16:] - The FILTER, see Filter.

This is a client initiated message. Servers are expected to reply with:

  • a series of zero or more Record messages representing all the matching records on the server initially, followed by a Locally Complete message, potentially followed by zero or more Record messages that flow in to the server after the initial response (so long as the query is still open), or
  • a Query Closed message if the query could not be served.

Queries MUST return results in anti-chronological order, from most recent backwards, up until Locally Complete is served, after which point they return records as they come in.

Unsubscribe

This is a client request to close an open subscription query.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x4 |  0  |  QUERY_ID |        LENGTH         |
 8  +-----------------------------------------------+
  • [0:1] - The type 0x3
  • [1:2] - Zeroed
  • [2:4] - QUERY_ID, two bytes indicating which query SHOULD be closed.
  • [4:8] - The byte length of this message, in little-endian format

This is a client initiated message. Servers are expected to reply with:

Submission

This is the submission of a record.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x5 |         0       |        LENGTH         |
 8  +-----------------------------------------------+
    | RECORD ...                                    |
    | ...                                           |
    +-----------------------------------------------+
  • [0:1] - The type 0x5
  • [1:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format
  • [8:] - RECORD is the record submitted

This is a client initiated message. Servers are expected to reply with:

BLOB Get

A BLOB is a Binary Large OBject. This message requests retrieval of a BLOB

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x8 |        0        |        LENGTH         |
 8  +-----------------------------------------------+
    | HASH   ...                                    |
    | ...                                           |
40  +-----------------------------------------------+
  • [0:1] - The type 0x8
  • [1:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format
  • [8:40] - the 256-bit BLAKE3 hash of the BLOB.

This is a client initiated message. Servers are expected to reply with:

BLOB Submission

A BLOB is a Binary Large OBject. This message submits a BLOB to the server for storage and later retrieval.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x7 |        0        |        LENGTH         |
 8  +-----------------------------------------------+
    | HASH   ...                                    |
    | ...                                           |
40  +-----------------------------------------------+
    | BLOB ...                                      |
    |                                          ...  |
  • [0:1] - The type 0x7
  • [1:4] - Zero
  • [4:8] - The byte length of this message, in little-endian format
  • [8:40] - the 256-bit BLAKE3 hash of the binary data.
  • [40:] - The binary data

The length of the binary data is (LENGTH - 40) with a maximum length of 4,294,967,256 (just shy of 4 GB). Larger blobs may be supported in the future using a sequence of messages to send parts.

This is a client initiated message. Servers are expected to reply with:

Servers MAY require authentication and MAY remember who submitted which BLOBs. Servers may limit the size of submitted BLOBs. Servers MAY provide some means for deleting BLOBs no longer in use. Servers MAY delete BLOBs that violate server policy. These issues are currently out of scope of this spec.

DHT Lookup

This requests that the server perform a DHT lookup on behalf of the client. rat

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x6 |SERV |     0     |        LENGTH         |
 8  +-----------------------------------------------+
    | PUBKEY ...                                    |
    |                                          ...  |
40  +-----------------------------------------------+
  • [0:1] - The type 0x7
  • [1:2] - Which kind of DHT lookup to do: 0 - User Bootstrap (mub25) 1 - Server Bootstrap (msb24)
  • [2:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format
  • [8:40] - The public key to lookup

This is a client initiated message. Servers are expected to reply with:


Server Messages

Hello Ack

NOTE: WebSockets sends HELLO ACK information out of band and does not utilize this message.

This is a reply to the client Hello message. It includes the highest Mosaic version that both parties support, as well as all of the application IDs that the client requested which the server can support.

It has the following format:


    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x90| RSLT|  0  | MV  |        LENGTH         |
 8  +-----------------------------------------------+
    | APP_ID                | ...                   |
    +-----------------------------------------------+
  • [0:1] - The type 0x90
  • [1:2] - RSLT indicates the result, typically SUCCESS but possibly DUPLICATE. Servers should refrain from using errors or rejections in this result and instead if necessary issue a Closing message.
  • [2:3] - Zeroed
  • [3:4] - MOSAIC_MAJOR_VERSION - The highest Mosaic major version number that both the server and the client supports, in little-endian format
  • [4:8] - The byte length of this message, in little-endian format
  • [8:] - A sequence of 32-bit Application IDs that the client requested and that the server can also support, in little-endian format

Closing

This is a server message indicating that the server is closing the connection. It is not necessarily in response to any client message, but could be sent in response to any client message.

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0xFE| RSLT|     0     |        LENGTH         |
 8  +-----------------------------------------------+
  • [0:1] - The type 0xFE
  • [1:2] - Result Code giving the reason. See Result Codes.
  • [2:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format

Record

This is a record returned from a query (Get, Query, or Subscribe).

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x80|  0  | QUERY_ID  |         LENGTH        |
 8  +-----------------------------------------------+
    | RECORD ...                                    |
    | ...                                           |
    +-----------------------------------------------+
  • [0:1] - The type 0x80
  • [1:2] - Zeroed
  • [2:4] - QUERY_ID indicates the client query that this record matched.
  • [4:8] - The byte length of this message, in little-endian format
  • [8:] - RECORD is the returned record.

This is a server response message in response to Get or Query or Subscribe.

Locally Complete

This is a message indicating that a query has served all matching local records, but remains open to serve matching records that subsequently arrive.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x81|  0  |  QUERY_ID |        LENGTH         |
 8  +-----------------------------------------------+
  • [0:1] - The type 0x81
  • [1:2] - Zeroed
  • [2:4] - QUERY_ID indicates the client query that is now locally complete.
  • [4:8] - The byte length of this message, in little-endian format

Query Closed

This is a message indicating that a query has been closed.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x82| RSLT|  QUERY_ID |        LENGTH         |
 8  +-----------------------------------------------+
  • [0:1] - The type 0x82
  • [1:2] - RESULT indicates the reason for closure.
  • [2:4] - QUERY_ID indicates the client query that is now closed. See Result Codes.
  • [4:8] - The byte length of this message, in little-endian format

Submission Result

This is a message returning the result of a Submission.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x83| RSLT|     0     |        LENGTH         |
 8  +-----------------------------------------------+
    | ID PREFIX bytes 0..8                          |
16  +-----------------------------------------------+
    | ID PREFIX bytes 8..16                         |
24  +-----------------------------------------------+
    | ID PREFIX bytes 16..24                        |
32  +-----------------------------------------------+
    | ID PREFIX bytes 24..32                        |
40  +-----------------------------------------------+
  • [0:1] - The type 0x83
  • [1:2] - RESULT which indicates the result of the submission. See Result Codes.
  • [2:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format
  • [8:40] - A 32-byte prefix of the 48-byte Id.

BLOB Result

This is a server response to a BLOB Get request returning the BLOB or an error condition.

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x86| RSLT|     0     |        LENGTH         |
 8  +-----------------------------------------------+
    | HASH   ...                                    |
    | ...                                           |
40  +-----------------------------------------------+
    | BLOB ...                                      |
    |                                          ...  |
  • [0:1] - The type 0x86
  • [1:2] - The result of the blob get request. See Result Codes.
  • [2:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format
  • [8:40] - the 256-bit BLAKE3 hash of the binary data.
  • [40:] - The binary data if the request was successful.

BLOB Submission Result

This is a server response to a BLOB Submission request.

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x85| RSLT|     0     |        LENGTH         |
 8  +-----------------------------------------------+
    | HASH   ...                                    |
    | ...                                           |
40  +-----------------------------------------------+
  • [0:1] - The type 0x85
  • [1:2] - The result. See Result Codes.
  • [2:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format
  • [8:40] - the 256-bit BLAKE3 hash of the binary data.

DHT Response

This is a server response to a DHT Lookup request.

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0x84| RSLT|     0     |        LENGTH         |
 8  +-----------------------------------------------+
    | DHT DATA ...                                  |
    |                                           ... |
    +-----------------------------------------------+
  • [0:1] - The type 0x84
  • [1:2] - The result. See Result Codes.
  • [2:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format
  • [8:] - The DHT data (unparsed) on success.

Unrecognized

This is a message indicating that the last message from the peer was not recognized.

When this is received over QUIC transport, the stream SHOULD be closed and further messaging can occur on other streams.

It has the following format:

    0     1     2     3     4     5     6     7     8
 0  +-----------------------------------------------+
    | 0xF0|        0        |        LENGTH         |
 8  +-----------------------------------------------+
  • [0:1] - The type 0xF0
  • [1:4] - Zeroed
  • [4:8] - The byte length of this message, in little-endian format

Result Codes

Multiple protocol messages contain a 1-byte result code. The definition of these codes is shared between message types and defined here.

  • 0 - UNDEFINED - This result code is not defined. It should not be used.

Successes:

  • 1 - SUCCESS - Generic success message
  • 2 - ACCEPTED - Accepted a submission
  • 3 - DUPLICATE - A record submitted is a duplicate of an existing record.
  • 4 - NO_CONSUMERS - Ephemeral record had no consumers.

Failures:

  • 16 - NOT_FOUND - Record or BLOB was not found

User Errors:

  • 32 - REQUIRES_AUTHENTICATION - Rejected as the request requires authentication
  • 33 - UNAUTHORIZED - Rejected as the pubkey is not authorized for the action
  • 36 - INVALID - Request was invalid
  • 37 - TOO_OPEN - A Query or Subscribe was too open, potentially matching too many records
  • 38 - TOO_LARGE - The submission was too large
  • 39 - TOO_FAST - Requests are coming in too fast from this client, or of this type.

User Rejections:

  • 48 - IP_TEMP_BANNED - IP address is temporarily banned
  • 49 - IP_PERM_BANNED - IP address is permanently banned
  • 50 - PUBKEY_TEMP_BANNED - Pubkey is temporarily banned
  • 51 - PUBKEY_PERM_BANNED - Pubkey is permanently banned

Server errors:

  • 64 - SHUTTING_DOWN - Server is shutting down
  • 65 - TEMPORARY ERROR - Temporary server error
  • 66 - PERSISTENT ERROR - Persistent server error
  • 67 - GENERAL ERROR - General server error

Protocol Extensions

Protocol extension negotiation is done on a transport-by-transport level. For QUIC transport this is done with the initial packet. For WebSockets transport this is done with the X-Mosaic-Extensions header. See the specific transport.

The following extensions have been defined: