</code></pre></div></div><p><codeclass="language-plaintext highlighter-rouge">signature</code> is the bytes of the signed <codeclass="language-plaintext highlighter-rouge">SHA3-256</code> of the payload, signed with the key of the author of the message. The node needs the signature to validate authorship of the message, so that the message can be relayed to third parties. If a signature is not present, but an author is provided by a layer below, the message is not to be relayed to third parties, and it is considered plausibly deniable.</p><p><codeclass="language-plaintext highlighter-rouge">payload</code> is the protobuf encoded content of the message, with the corresponding <codeclass="language-plaintext highlighter-rouge">type</code> set.</p><h2id="encoding"><ahref="#encoding"class="anchor-heading"aria-labelledby="encoding"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Encoding </h2><p>The node encodes the payload using <ahref="https://developers.google.com/protocol-buffers">Protobuf</a></p><h2id="types-of-messages"><ahref="#types-of-messages"class="anchor-heading"aria-labelledby="types-of-messages"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Types of messages </h2><h3id="message"><ahref="#message"class="anchor-heading"aria-labelledby="message"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Message </h3><p>The type <codeclass="language-plaintext highlighter-rouge">ChatMessage</code> represents a chat message exchanged between clients.</p><h4id="payload"><ahref="#payload"class="anchor-heading"aria-labelledby="payload"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Payload </h4><p>The protobuf description is:</p><divclass="language-protobuf highlighter-rouge"><divclass="highlight"><preclass="highlight"><code><spanclass="kd">message</span><spanclass="nc">ChatMessage</span><spanclass="p">{</span>
<spanclass="c1">// Lamport timestamp of the chat message</span>
</code></pre></div></div><h4id="payload-1"><ahref="#payload-1"class="anchor-heading"aria-labelledby="payload-1"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Payload </h4><divclass="table-wrapper"><table><thead><tr><th>Field</th><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>clock</td><td><codeclass="language-plaintext highlighter-rouge">uint64</code></td><td>The clock of the chat</td></tr><tr><td>2</td><td>timestamp</td><td><codeclass="language-plaintext highlighter-rouge">uint64</code></td><td>The sender timestamp at message creation</td></tr><tr><td>3</td><td>text</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The content of the message</td></tr><tr><td>4</td><td>response_to</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The ID of the message replied to</td></tr><tr><td>5</td><td>ens_name</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The ENS name of the user sending the message</td></tr><tr><td>6</td><td>chat_id</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The local ID of the chat the message is sent to</td></tr><tr><td>7</td><td>message_type</td><td><codeclass="language-plaintext highlighter-rouge">MessageType</code></td><td>The type of message, different for one-to-one, public or group chats</td></tr><tr><td>8</td><td>content_type</td><td><codeclass="language-plaintext highlighter-rouge">ContentType</code></td><td>The type of the content of the message</td></tr><tr><td>9</td><td>payload</td><td><codeclass="language-plaintext highlighter-rouge">Sticker|nil</code></td><td>The payload of the message based on the content type</td></tr></tbody></table></div><h4id="content-types"><ahref="#content-types"class="anchor-heading"aria-labelledby="content-types"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Content types </h4><p>A node requires content types for a proper interpretation of incoming messages. Not each message is plain text but may carry different information.</p><p>The following content types MUST be supported:</p><ul><li><codeclass="language-plaintext highlighter-rouge">TEXT_PLAIN</code> identifies a message which content is a plaintext.</li></ul><p>There are other content types that MAY be implemented by the client:</p><ul><li><codeclass="language-plaintext highlighter-rouge">STICKER</code></li><li><codeclass="language-plaintext highlighter-rouge">STATUS</code></li><li><codeclass="language-plaintext highlighter-rouge">EMOJI</code></li><li><codeclass="language-plaintext highlighter-rouge">TRANSACTION_COMMAND</code></li></ul><h5id="mentions"><ahref="#mentions"class="anchor-heading"aria-labelledby="mentions"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Mentions </h5><p>A mention MUST be represented as a string with the <codeclass="language-plaintext highlighter-rouge">@0xpk</code> format, where <codeclass="language-plaintext highlighter-rouge">pk</code> is the public key of the <ahref="https://specs.status.im/spec/2">user account</a> to be mentioned, within the <codeclass="language-plaintext highlighter-rouge">text</code> field of a message with content_type <codeclass="language-plaintext highlighter-rouge">TEXT_PLAIN</code>. A message MAY contain more than one mention. This specification RECOMMENDs that the application does not require the user to enter the entire pk. This specification RECOMMENDs that the application allows the user to create a mention by typing @ followed by the related ENS or 3-word pseudonym. This specification RECOMMENDs that the application provides the user auto-completion functionality to create a mention. For better user experience, the client SHOULD display a known <ahref="https://specs.status.im/spec/2#contact-verification">ens name or the 3-word pseudonym corresponding to
</code></pre></div></div><h4id="message-types"><ahref="#message-types"class="anchor-heading"aria-labelledby="message-types"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Message types </h4><p>A node requires message types to decide how to encrypt a particular message and what metadata needs to be attached when passing a message to the transport layer. For more on this, see <ahref="3-whisper-usage.md">3/WHISPER-USAGE</a> and <ahref="10-waku-usage.md">10/WAKU-USAGE</a>.</p><!-- TODO: This reference is a bit odd, considering the layer payloads should interact with is Secure Transport, and not Whisper/Waku. This requires more detail --><p>The following messages types MUST be supported:</p><ul><li><codeclass="language-plaintext highlighter-rouge">ONE_TO_ONE</code> is a message to the public group</li><li><codeclass="language-plaintext highlighter-rouge">PUBLIC_GROUP</code> is a private message</li><li><codeclass="language-plaintext highlighter-rouge">PRIVATE_GROUP</code> is a message to the private group.</li></ul><h4id="clock-vs-timestamp-and-message-ordering"><ahref="#clock-vs-timestamp-and-message-ordering"class="anchor-heading"aria-labelledby="clock-vs-timestamp-and-message-ordering"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Clock vs Timestamp and message ordering </h4><p>If a user sends a new message before the messages sent while the user was offline are received, the new message is supposed to be displayed last in a chat. This is where the basic algorithm of Lamport timestamp would fall short as it’s only meant to order causally related events.</p><p>The status client therefore makes a “bid”, speculating that it will beat the current chat-timestamp, s.t. the status client’s Lamport timestamp format is: <codeclass="language-plaintext highlighter-rouge">clock = </code>max({timestamp}, chat_clock + 1)`</p><p>This will satisfy the Lamport requirement, namely: a -> b then T(a) < T(b)</p><p><codeclass="language-plaintext highlighter-rouge">timestamp</code> MUST be Unix time calculated, when the node creates the message, in milliseconds. This field SHOULD not be relied upon for message ordering.</p><p><codeclass="language-plaintext highlighter-rouge">clock</code> SHOULD be calculated using the algorithm of <ahref="https://en.wikipedia.org/wiki/Lamport_timestamps">Lamport timestamps</a>. When there are messages available in a chat, the node calculates <codeclass="language-plaintext highlighter-rouge">clock</code>’s value based on the last received message in a particular chat: <codeclass="language-plaintext highlighter-rouge">max(timeNowInMs, last-message-clock-value + 1)</code>. If there are no messages, <codeclass="language-plaintext highlighter-rouge">clock</code> is initialized with <codeclass="language-plaintext highlighter-rouge">timestamp</code>’s value.</p><p>Messages with a <codeclass="language-plaintext highlighter-rouge">clock</code> greater than <codeclass="language-plaintext highlighter-rouge">120</code> seconds over the Whisper/Waku timestamp SHOULD be discarded, in order to avoid malicious users to increase the <codeclass="language-plaintext highlighter-rouge">clock</code> of a chat arbitrarily.</p><p>Messages with a <codeclass="language-plaintext highlighter-rouge">clock</code> less than <codeclass="language-plaintext highlighter-rouge">120</code> seconds under the Whisper/Waku timestamp might indicate an attempt to insert messages in the chat history which is not distinguishable from a <codeclass="language-plaintext highlighter-rouge">datasync</code> layer re-transit event. A client MAY mark this messages with a warning to the user, or discard them.</p><p>The node uses <codeclass="language-plaintext highlighter-rouge">clock</code> value for the message ordering. The algorithm used, and the distributed nature of the system produces casual ordering, which might produce counter-intuitive results in some edge cases. For example, when a user joins a public chat
</code></pre></div></div><h4id="payload-2"><ahref="#payload-2"class="anchor-heading"aria-labelledby="payload-2"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Payload </h4><divclass="table-wrapper"><table><thead><tr><th>Field</th><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>clock</td><td><codeclass="language-plaintext highlighter-rouge">uint64</code></td><td>The clock of the chat with the user</td></tr><tr><td>2</td><td>ens_name</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The ENS name if set</td></tr><tr><td>3</td><td>profile_image</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The base64 encoded profile picture of the user</td></tr></tbody></table></div><h4id="contact-update-1"><ahref="#contact-update-1"class="anchor-heading"aria-labelledby="contact-update-1"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Contact update </h4><p>A client SHOULD send a <codeclass="language-plaintext highlighter-rouge">ContactUpdate</code> to all the contacts each time:</p><ul><li>The ens_name has changed</li><li>A user edits the profile image</li></ul><p>A client SHOULD also periodically send a <codeclass="language-plaintext highlighter-rouge">ContactUpdate</code> to all the contacts, the interval is up to the client, the Status official client sends these updates every 48 hours.</p><h3id="syncinstallationcontact"><ahref="#syncinstallationcontact"class="anchor-heading"aria-labelledby="syncinstallationcontact"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> SyncInstallationContact </h3><p>The node uses <codeclass="language-plaintext highlighter-rouge">SyncInstallationContact</code> messages to synchronize in a best-effort the contacts to other devices.</p><divclass="language-protobuf highlighter-rouge"><divclass="highlight"><preclass="highlight"><code><spanclass="kd">message</span><spanclass="nc">SyncInstallationContact</span><spanclass="p">{</span>
</code></pre></div></div><h4id="payload-3"><ahref="#payload-3"class="anchor-heading"aria-labelledby="payload-3"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Payload </h4><divclass="table-wrapper"><table><thead><tr><th>Field</th><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>clock</td><td><codeclass="language-plaintext highlighter-rouge">uint64</code></td><td>clock value of the chat</td></tr><tr><td>2</td><td>id</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>id of the contact synced</td></tr><tr><td>3</td><td>profile_image</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td><codeclass="language-plaintext highlighter-rouge">base64</code> encoded profile picture of the user</td></tr><tr><td>4</td><td>ens_name</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>ENS name of the contact</td></tr><tr><td>5</td><td><codeclass="language-plaintext highlighter-rouge">array[string]</code></td><td>Array of <codeclass="language-plaintext highlighter-rouge">system_tags</code> for the user, this can currently be: <codeclass="language-plaintext highlighter-rouge">":contact/added", ":contact/blocked", ":contact/request-received"</code></td><td></td></tr></tbody></table></div><h3id="syncinstallationpublicchat"><ahref="#syncinstallationpublicchat"class="anchor-heading"aria-labelledby="syncinstallationpublicchat"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> SyncInstallationPublicChat </h3><p>The node uses <codeclass="language-plaintext highlighter-rouge">SyncInstallationPublicChat</code> message to synchronize in a best-effort the public chats to other devices.</p><divclass="language-protobuf highlighter-rouge"><divclass="highlight"><preclass="highlight"><code><spanclass="kd">message</span><spanclass="nc">SyncInstallationPublicChat</span><spanclass="p">{</span>
</code></pre></div></div><h4id="payload-4"><ahref="#payload-4"class="anchor-heading"aria-labelledby="payload-4"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Payload </h4><divclass="table-wrapper"><table><thead><tr><th>Field</th><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>clock</td><td><codeclass="language-plaintext highlighter-rouge">uint64</code></td><td>clock value of the chat</td></tr><tr><td>2</td><td>id</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>id of the chat synced</td></tr></tbody></table></div><h3id="pairinstallation"><ahref="#pairinstallation"class="anchor-heading"aria-labelledby="pairinstallation"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> PairInstallation </h3><p>The node uses <codeclass="language-plaintext highlighter-rouge">PairInstallation</code> messages to propagate information about a device to its paired devices.</p><divclass="language-protobuf highlighter-rouge"><divclass="highlight"><preclass="highlight"><code><spanclass="kd">message</span><spanclass="nc">PairInstallation</span><spanclass="p">{</span>
</code></pre></div></div><h4id="payload-5"><ahref="#payload-5"class="anchor-heading"aria-labelledby="payload-5"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Payload </h4><divclass="table-wrapper"><table><thead><tr><th>Field</th><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>clock</td><td><codeclass="language-plaintext highlighter-rouge">uint64</code></td><td>clock value of the chat</td></tr><tr><td>2</td><td>installation_id</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>A randomly generated id that identifies this device</td></tr><tr><td>3</td><td>device_type</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The OS of the device <codeclass="language-plaintext highlighter-rouge">ios</code>,<codeclass="language-plaintext highlighter-rouge">android</code> or <codeclass="language-plaintext highlighter-rouge">desktop</code></td></tr><tr><td>4</td><td>name</td><td><codeclass="language-plaintext highlighter-rouge">string</code></td><td>The self-assigned name of the device</td></tr></tbody></table></div><h3id="membershipupdatemessage-and-membershipupdateevent"><ahref="#membershipupdatemessage-and-membershipupdateevent"class="anchor-heading"aria-labelledby="membershipupdatemessage-and-membershipupdateevent"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> MembershipUpdateMessage and MembershipUpdateEvent </h3><p><codeclass="language-plaintext highlighter-rouge">MembershipUpdateEvent</code> is a message used to propagate information about group membership changes in a group chat. The details are in the <ahref="./../draft/7-group-chat.md">Group chats specs</a>.</p><h2id="upgradability"><ahref="#upgradability"class="anchor-heading"aria-labelledby="upgradability"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Upgradability </h2><p>There are two ways to upgrade the protocol without breaking compatibility:</p><ul><li>A node always supports accretion</li><li>A node does not support deletion of existing fields or messages, which might break compatibility</li></ul><h2id="security-considerations"><ahref="#security-considerations"class="anchor-heading"aria-labelledby="security-considerations"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Security Considerations </h2><p>-</p><h2id="changelog"><ahref="#changelog"class="anchor-heading"aria-labelledby="changelog"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Changelog </h2><h3id="version-03"><ahref="#version-03"class="anchor-heading"aria-labelledby="version-03"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Version 0.3 </h3><p>Released <ahref="https://github.com/status-im/specs/commit/664dd1c9df6ad409e4c007fefc8c8945b8d324e8">May 22, 2020</a></p><ul><li>Added language to include Waku in all relevant places</li></ul><h2id="copyright"><ahref="#copyright"class="anchor-heading"aria-labelledby="copyright"><svgviewBox="0 0 16 16"aria-hidden="true"><usexlink:href="#svg-link"></use></svg></a> Copyright </h2><p>Copyright and related rights waived via <ahref="https://creativecommons.org/publicdomain/zero/1.0/">CC0</a>.</p></div></div><divclass="search-overlay"></div></div></body></html>