specs/draft/6.html

131 lines
52 KiB
HTML
Raw Normal View History

2021-11-16 14:54:10 +00:00
<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <title>6/PAYLOADS - Status Specification</title> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> <link rel="stylesheet" href="/assets/css/just-the-docs-default.css"> <script type="text/javascript" src="/assets/js/vendor/lunr.min.js"></script> <script type="text/javascript" src="/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.7.1 --> <title>6/PAYLOADS | Status Specification</title> <meta name="generator" content="Jekyll v4.2.1" /> <meta property="og:title" content="6/PAYLOADS" /> <meta property="og:locale" content="en_US" /> <link rel="canonical" href="https://specs.status.im/draft/6" /> <meta property="og:url" content="https://specs.status.im/draft/6" /> <meta property="og:site_name" content="Status Specification" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="6/PAYLOADS" /> <script type="application/ld+json"> {"@type":"WebPage","url":"https://specs.status.im/draft/6","headline":"6/PAYLOADS","@context":"https://schema.org"}</script> <!-- End Jekyll SEO tag --> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> </svg> <div class="side-bar"> <div class="site-header"> <a href="https://specs.status.im/" class="site-title lh-tight"> Status Specification </a> <a href="#" id="menu-button" class="site-button"> <svg viewBox="0 0 24 24" class="icon"><use xlink:href="#svg-menu"></use></svg> </a> </div> <nav role="navigation" aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="https://specs.status.im/stable/" class="nav-list-link">Stable specs</a><ul class="nav-list "><li class="nav-list-item "><a href="https://specs.status.im/stable/1" class="nav-list-link">1/CLIENT</a></li><li class=
<span class="kt">bytes</span> <span class="na">signature</span> <span class="o">=</span> <span class="mi">4001</span><span class="p">;</span>
<span class="kt">bytes</span> <span class="na">payload</span> <span class="o">=</span> <span class="mi">4002</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <p><code class="language-plaintext highlighter-rouge">signature</code> is the bytes of the signed <code class="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> <h2 id="encoding"> <a href="#encoding" class="anchor-heading" aria-labelledby="encoding"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Encoding </h2> <p>The node encodes the payload using <a href="https://developers.google.com/protocol-buffers">Protobuf</a></p> <h2 id="types-of-messages"> <a href="#types-of-messages" class="anchor-heading" aria-labelledby="types-of-messages"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Types of messages </h2> <h3 id="message"> <a href="#message" class="anchor-heading" aria-labelledby="message"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Message </h3> <p>The type <code class="language-plaintext highlighter-rouge">ChatMessage</code> represents a chat message exchanged between clients.</p> <h4 id="payload"> <a href="#payload" class="anchor-heading" aria-labelledby="payload"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Payload </h4> <p>The protobuf description is:</p> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">message</span> <span class="nc">ChatMessage</span> <span class="p">{</span>
<span class="c1">// Lamport timestamp of the chat message</span>
<span class="kt">uint64</span> <span class="na">clock</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="c1">// Unix timestamps in milliseconds, currently not used as we use Whisper/Waku as more reliable, but here</span>
<span class="c1">// so that we don't rely on it</span>
<span class="kt">uint64</span> <span class="na">timestamp</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="c1">// Text of the message</span>
<span class="kt">string</span> <span class="na">text</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="c1">// Id of the message that we are replying to</span>
<span class="kt">string</span> <span class="na">response_to</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="c1">// Ens name of the sender</span>
<span class="kt">string</span> <span class="na">ens_name</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="c1">// Chat id, this field is symmetric for public-chats and private group chats,</span>
<span class="c1">// but asymmetric in case of one-to-ones, as the sender will use the chat-id</span>
<span class="c1">// of the received, while the receiver will use the chat-id of the sender.</span>
<span class="kt">string</span> <span class="na">chat_id</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span>
<span class="c1">// The type of message (public/one-to-one/private-group-chat)</span>
<span class="n">MessageType</span> <span class="na">message_type</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span>
<span class="c1">// The type of the content of the message</span>
<span class="n">ContentType</span> <span class="na">content_type</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span>
<span class="k">oneof</span> <span class="n">payload</span> <span class="p">{</span>
<span class="n">StickerMessage</span> <span class="na">sticker</span> <span class="o">=</span> <span class="mi">9</span><span class="p">;</span>
<span class="n">ImageMessage</span> <span class="na">image</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
<span class="n">AudioMessage</span> <span class="na">audio</span> <span class="o">=</span> <span class="mi">11</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">enum</span> <span class="n">ContentType</span> <span class="p">{</span>
<span class="na">UNKNOWN_CONTENT_TYPE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="na">TEXT_PLAIN</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="na">STICKER</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="na">STATUS</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="na">EMOJI</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="na">TRANSACTION_COMMAND</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="c1">// Only local</span>
<span class="na">SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span>
<span class="na">IMAGE</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span>
<span class="na">AUDIO</span> <span class="o">=</span> <span class="mi">8</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div> <h4 id="payload-1"> <a href="#payload-1" class="anchor-heading" aria-labelledby="payload-1"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Payload </h4> <div class="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><code class="language-plaintext highlighter-rouge">uint64</code></td> <td>The clock of the chat</td> </tr> <tr> <td>2</td> <td>timestamp</td> <td><code class="language-plaintext highlighter-rouge">uint64</code></td> <td>The sender timestamp at message creation</td> </tr> <tr> <td>3</td> <td>text</td> <td><code class="language-plaintext highlighter-rouge">string</code></td> <td>The content of the message</td> </tr> <tr> <td>4</td> <td>response_to</td> <td><code class="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><code class="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><code class="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><code class="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><code class="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><code class="language-plaintext highlighter-rouge">Sticker</code> I <code class="language-plaintext highlighter-rouge">Image</code> I <code class="language-plaintext highlighter-rouge">Audio</code> I <code class="language-plaintext highlighter-rouge">nil</code></td> <td>The payload of the message based on the content type</td> </tr> </tbody> </table></div> <h4 id="content-types"> <a href="#content-types" class="anchor-heading" aria-labelledby="content-types"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink: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><code class="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><code class="language-plaintext highlighter-rouge">STICKER</code></li> <li><code class="language-plaintext highlighter-rouge">STATUS</code></li> <li><code class="language-plaintext highlighter-rouge">EMOJI</code></li> <li><code class="language-plaintext highlighter-rouge">TRANSACTION_COMMAND</code></li> <li><code class="language-plaintext highlighter-rouge">IMAGE</code></li> <li><code class="language-plaintext highlighter-rouge">AUDIO</code></li> </ul> <h5 id="mentions"> <a href="#mentions" class="anchor-heading" aria-labelledby="mentions"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Mentions </h5> <p>A mention MUST be represented as a string with the <code class="language-plaintext highlighter-rouge">@0xpk</code> format, where <code class="language-plaintext highlighter-rouge">pk</code> is the public key of the <a href="https://specs.status.im/spec/2">user account</a> to be mentioned, within the <code class="language-plaintext highlighter-rouge">text</code> field of a message with content_type <code class="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 @ follo
<span class="kt">string</span> <span class="na">hash</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">int32</span> <span class="na">pack</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <h5 id="image-content-type"> <a href="#image-content-type" class="anchor-heading" aria-labelledby="image-content-type"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Image content type </h5> <p>A <code class="language-plaintext highlighter-rouge">ChatMessage</code> with <code class="language-plaintext highlighter-rouge">IMAGE</code> <code class="language-plaintext highlighter-rouge">Content/Type</code> MUST also specify the <code class="language-plaintext highlighter-rouge">payload</code> of the image and the <code class="language-plaintext highlighter-rouge">type</code>.</p> <p>Clients MUST sanitize the payload before accessing its content, in particular:</p> <ul> <li>Clients MUST choose a secure decoder</li> <li>Clients SHOULD strip metadata if present without parsing/decoding it</li> <li>Clients SHOULD NOT add metadata/exif when sending an image file for privacy and security reasons</li> <li>Clients MUST make sure that the transport layer constraints the size of the payload to limit they are able to handle securely</li> </ul> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">message</span> <span class="nc">ImageMessage</span> <span class="p">{</span>
<span class="kt">bytes</span> <span class="na">payload</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">ImageType</span> <span class="na">type</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kd">enum</span> <span class="n">ImageType</span> <span class="p">{</span>
<span class="na">UNKNOWN_IMAGE_TYPE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="na">PNG</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="na">JPEG</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="na">WEBP</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="na">GIF</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div> <h5 id="audio-content-type"> <a href="#audio-content-type" class="anchor-heading" aria-labelledby="audio-content-type"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Audio content type </h5> <p>A <code class="language-plaintext highlighter-rouge">ChatMessage</code> with <code class="language-plaintext highlighter-rouge">AUDIO</code> <code class="language-plaintext highlighter-rouge">Content/Type</code> MUST also specify the <code class="language-plaintext highlighter-rouge">payload</code> of the audio, the <code class="language-plaintext highlighter-rouge">type</code> and the duration in milliseconds (<code class="language-plaintext highlighter-rouge">duration_ms</code>).</p> <p>Clients MUST sanitize the payload before accessing its content, in particular:</p> <ul> <li>Clients MUST choose a secure decoder</li> <li>Clients SHOULD strip metadata if present without parsing/decoding it</li> <li>Clients SHOULD NOT add metadata/exif when sending an audio file for privacy and security reasons</li> <li>Clients MUST make sure that the transport layer constraints the size of the payload to limit they are able to handle securely</li> </ul> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">message</span> <span class="nc">AudioMessage</span> <span class="p">{</span>
<span class="kt">bytes</span> <span class="na">payload</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">AudioType</span> <span class="na">type</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kt">uint64</span> <span class="na">duration_ms</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="kd">enum</span> <span class="n">AudioType</span> <span class="p">{</span>
<span class="na">UNKNOWN_AUDIO_TYPE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="na">AAC</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="na">AMR</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</code></pre></div></div> <h4 id="message-types"> <a href="#message-types" class="anchor-heading" aria-labelledby="message-types"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink: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 <a href="./../stable/3-whisper-usage.md">3/WHISPER-USAGE</a> and <a href="./../stable/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><code class="language-plaintext highlighter-rouge">ONE_TO_ONE</code> is a message to the public group</li> <li><code class="language-plaintext highlighter-rouge">PUBLIC_GROUP</code> is a private message</li> <li><code class="language-plaintext highlighter-rouge">PRIVATE_GROUP</code> is a message to the private group.</li> </ul> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">enum</span> <span class="n">MessageType</span> <span class="p">{</span>
<span class="na">UNKNOWN_MESSAGE_TYPE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="na">ONE_TO_ONE</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="na">PUBLIC_GROUP</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="na">PRIVATE_GROUP</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="c1">// Only local</span>
<span class="na">SYSTEM_MESSAGE_PRIVATE_GROUP</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <h4 id="clock-vs-timestamp-and-message-ordering"> <a href="#clock-vs-timestamp-and-message-ordering" class="anchor-heading" aria-labelledby="clock-vs-timestamp-and-message-ordering"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink: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 its 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 clients Lamport timestamp format is: <code class="language-plaintext highlighter-rouge">clock = </code>max({timestamp}, chat_clock + 1)`</p> <p>This will satisfy the Lamport requirement, namely: a -&gt; b then T(a) &lt; T(b)</p> <p><code class="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><code class="language-plaintext highlighter-rouge">clock</code> SHOULD be calculated using the algorithm of <a href="https://en.wikipedia.org/wiki/Lamport_timestamps">Lamport timestamps</a>. When there are messages available in a chat, the node calculates <code class="language-plaintext highlighter-rouge">clock</code>s value based on the last received message in a particular chat: <code class="language-plaintext highlighter-rouge">max(timeNowInMs, last-message-clock-value + 1)</code>. If there are no messages, <code class="language-plaintext highlighter-rouge">clock</code> is initialized with <code class="language-plaintext highlighter-rouge">timestamp</code>s value.</p> <p>Messages with a <code class="language-plaintext highlighter-rouge">clock</code> greater than <code class="language-plaintext highlighter-rouge">120</code> seconds over the Whisper/Waku timestamp SHOULD be discarded, in order to avoid malicious users to increase the <code class="language-plaintext highlighter-rouge">clock</code> of a chat arbitrarily.</p> <p>Messages with a <code class="language-plaintext highlighter-rouge">clock</code> less than <code class="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 <code class="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 <code class="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 and sends a message before receiving the exist messages, their message <code class="language-plaintext highlighter-rouge">clock</code> value might be lower and the message will end up in the past when the historical messages are fetched.</p> <h4 id="chats"> <a href="#chats" class="anchor-heading" aria-labelledby="chats"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Chats </h4> <p>Chat is a structure that helps organize messages. Its usually desired to display messages only from a single recipient, or a group of recipients at a time and chats help to achieve that.</p> <p>All incoming messages can be matched against a chat. The below table describes how to calculate a chat ID for each message type.</p> <div class="table-wrapper"><table> <thead> <tr> <th>Message Type</th> <th>Chat ID Calculation</th> <th>Direction</th> <th>Comment</th> </tr> </thead> <tbody> <tr> <td>PUBLIC_GROUP</td> <td>chat ID is equal to a public channel name; it should equal <code class="language-plaintext highlighter-rouge">chatId
<span class="kt">uint64</span> <span class="na">clock</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">ens_name</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">profile_image</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <h4 id="payload-2"> <a href="#payload-2" class="anchor-heading" aria-labelledby="payload-2"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Payload </h4> <div class="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><code class="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><code class="language-plaintext highlighter-rouge">string</code></td> <td>The ENS name if set</td> </tr> <tr> <td>3</td> <td>profile_image</td> <td><code class="language-plaintext highlighter-rouge">string</code></td> <td>The base64 encoded profile picture of the user</td> </tr> </tbody> </table></div> <h4 id="contact-update-1"> <a href="#contact-update-1" class="anchor-heading" aria-labelledby="contact-update-1"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Contact update </h4> <p>A client SHOULD send a <code class="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 <code class="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> <h3 id="emojireaction"> <a href="#emojireaction" class="anchor-heading" aria-labelledby="emojireaction"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> EmojiReaction </h3> <p><code class="language-plaintext highlighter-rouge">EmojiReaction</code>s represents a users “reaction” to a specific chat message. For more information about the concept of emoji reactions see <a href="https://en.wikipedia.org/wiki/Facebook_like_button#Use_on_Facebook">Facebook Reactions</a>.</p> <p>This specification RECOMMENDS that the UI/UX implementation of sending <code class="language-plaintext highlighter-rouge">EmojiReactions</code> requires only a single click operation, as users have an expectation that emoji reactions are effortless and simple to perform.</p> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">message</span> <span class="nc">EmojiReaction</span> <span class="p">{</span>
<span class="c1">// clock Lamport timestamp of the chat message</span>
<span class="kt">uint64</span> <span class="na">clock</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="c1">// chat_id the ID of the chat the message belongs to, for query efficiency the chat_id is stored in the db even though the</span>
<span class="c1">// target message also stores the chat_id</span>
<span class="kt">string</span> <span class="na">chat_id</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="c1">// message_id the ID of the target message that the user wishes to react to</span>
<span class="kt">string</span> <span class="na">message_id</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="c1">// message_type is (somewhat confusingly) the ID of the type of chat the message belongs to</span>
<span class="n">MessageType</span> <span class="na">message_type</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="c1">// type the ID of the emoji the user wishes to react with</span>
<span class="n">Type</span> <span class="na">type</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="kd">enum</span> <span class="n">Type</span> <span class="p">{</span>
<span class="na">UNKNOWN_EMOJI_REACTION_TYPE</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="na">LOVE</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="na">THUMBS_UP</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="na">THUMBS_DOWN</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="na">LAUGH</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="na">SAD</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="na">ANGRY</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// whether this is a retraction of a previously sent emoji</span>
<span class="kt">bool</span> <span class="na">retracted</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <p>Clients MUST specify <code class="language-plaintext highlighter-rouge">clock</code>, <code class="language-plaintext highlighter-rouge">chat_id</code>, <code class="language-plaintext highlighter-rouge">message_id</code>, <code class="language-plaintext highlighter-rouge">type</code> and <code class="language-plaintext highlighter-rouge">message_type</code>.</p> <p>This specification RECOMMENDS that the UI/UX implementation of retracting an <code class="language-plaintext highlighter-rouge">EmojiReaction</code>s requires only a single click operation, as users have an expectation that emoji reaction removals are effortless and simple to perform.</p> <h3 id="syncinstallationcontact"> <a href="#syncinstallationcontact" class="anchor-heading" aria-labelledby="syncinstallationcontact"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> SyncInstallationContact </h3> <p>The node uses <code class="language-plaintext highlighter-rouge">SyncInstallationContact</code> messages to synchronize in a best-effort the contacts to other devices.</p> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">message</span> <span class="nc">SyncInstallationContact</span> <span class="p">{</span>
<span class="kt">uint64</span> <span class="na">clock</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">id</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">profile_image</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">ens_name</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="kt">uint64</span> <span class="na">last_updated</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="k">repeated</span> <span class="kt">string</span> <span class="na">system_tags</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <h4 id="payload-3"> <a href="#payload-3" class="anchor-heading" aria-labelledby="payload-3"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Payload </h4> <div class="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><code class="language-plaintext highlighter-rouge">uint64</code></td> <td>clock value of the chat</td> </tr> <tr> <td>2</td> <td>id</td> <td><code class="language-plaintext highlighter-rouge">string</code></td> <td>id of the contact synced</td> </tr> <tr> <td>3</td> <td>profile_image</td> <td><code class="language-plaintext highlighter-rouge">string</code></td> <td><code class="language-plaintext highlighter-rouge">base64</code> encoded profile picture of the user</td> </tr> <tr> <td>4</td> <td>ens_name</td> <td><code class="language-plaintext highlighter-rouge">string</code></td> <td>ENS name of the contact</td> </tr> <tr> <td>5</td> <td><code class="language-plaintext highlighter-rouge">array[string]</code></td> <td>Array of <code class="language-plaintext highlighter-rouge">system_tags</code> for the user, this can currently be: <code class="language-plaintext highlighter-rouge">":contact/added", ":contact/blocked", ":contact/request-received"</code></td> <td> </td> </tr> </tbody> </table></div> <h3 id="syncinstallationpublicchat"> <a href="#syncinstallationpublicchat" class="anchor-heading" aria-labelledby="syncinstallationpublicchat"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> SyncInstallationPublicChat </h3> <p>The node uses <code class="language-plaintext highlighter-rouge">SyncInstallationPublicChat</code> message to synchronize in a best-effort the public chats to other devices.</p> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">message</span> <span class="nc">SyncInstallationPublicChat</span> <span class="p">{</span>
<span class="kt">uint64</span> <span class="na">clock</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">id</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <h4 id="payload-4"> <a href="#payload-4" class="anchor-heading" aria-labelledby="payload-4"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Payload </h4> <div class="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><code class="language-plaintext highlighter-rouge">uint64</code></td> <td>clock value of the chat</td> </tr> <tr> <td>2</td> <td>id</td> <td><code class="language-plaintext highlighter-rouge">string</code></td> <td>id of the chat synced</td> </tr> </tbody> </table></div> <h3 id="pairinstallation"> <a href="#pairinstallation" class="anchor-heading" aria-labelledby="pairinstallation"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> PairInstallation </h3> <p>The node uses <code class="language-plaintext highlighter-rouge">PairInstallation</code> messages to propagate information about a device to its paired devices.</p> <div class="language-protobuf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">message</span> <span class="nc">PairInstallation</span> <span class="p">{</span>
<span class="kt">uint64</span> <span class="na">clock</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">installation_id</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">device_type</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="kt">string</span> <span class="na">name</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div> <h4 id="payload-5"> <a href="#payload-5" class="anchor-heading" aria-labelledby="payload-5"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Payload </h4> <div class="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><code class="language-plaintext highlighter-rouge">uint64</code></td> <td>clock value of the chat</td> </tr> <tr> <td>2</td> <td>installation_id</td> <td><code class="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><code class="language-plaintext highlighter-rouge">string</code></td> <td>The OS of the device <code class="language-plaintext highlighter-rouge">ios</code>,<code class="language-plaintext highlighter-rouge">android</code> or <code class="language-plaintext highlighter-rouge">desktop</code></td> </tr> <tr> <td>4</td> <td>name</td> <td><code class="language-plaintext highlighter-rouge">string</code></td> <td>The self-assigned name of the device</td> </tr> </tbody> </table></div> <h3 id="membershipupdatemessage-and-membershipupdateevent"> <a href="#membershipupdatemessage-and-membershipupdateevent" class="anchor-heading" aria-labelledby="membershipupdatemessage-and-membershipupdateevent"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> MembershipUpdateMessage and MembershipUpdateEvent </h3> <p><code class="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 <a href="./7-group-chat.md">Group chats specs</a>.</p> <h2 id="upgradability"> <a href="#upgradability" class="anchor-heading" aria-labelledby="upgradability"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink: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> <h2 id="security-considerations"> <a href="#security-considerations" class="anchor-heading" aria-labelledby="security-considerations"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Security Considerations </h2> <p>-</p> <h2 id="changelog"> <a href="#changelog" class="anchor-heading" aria-labelledby="changelog"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Changelog </h2> <h3 id="version-05"> <a href="#version-05" class="anchor-heading" aria-labelledby="version-05"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Version 0.5 </h3> <p>Released <a href="https://github.com/status-im/specs/commit/968fafff23cdfc67589b34dd64015de29aaf41f0">August 25, 2020</a></p> <ul> <li>Added support for emoji reactions</li> </ul> <h3 id="version-04"> <a href="#version-04" class="anchor-heading" aria-labelledby="version-04"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Version 0.4 </h3> <p>Released <a href="https://github.com/status-im/specs/commit/ad45cd5fed3c0f79dfa472253a404f670dd47396">July 16, 2020</a></p> <ul> <li>Added support for images</li> <li>Added support for audio</li> </ul> <h3 id="version-03"> <a href="#version-03" class="anchor-heading" aria-labelledby="version-03"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Version 0.3 </h3> <p>Released <a href="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> <h2 id="copyright"> <a href="#copyright" class="anchor-heading" aria-labelledby="copyright"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></s