diff --git a/README.md b/README.md index 489d961..cfcf1a7 100644 --- a/README.md +++ b/README.md @@ -16,28 +16,11 @@ its various capabilities. 1. Create an issue for a new Status Improvement Proposal (SIP) or some bug that you'd like to address 2. Create a corresponding PR and ping some existing SIP editors for review -If you need help, ask in #protocol at Status / Discord. +If you need help, ask in #protocol at [Status / Discord](https://discord.gg/3Exux7Y). -### Spellcheck +### Specification style guidelines -To run the spellchecker locally, you must install [pyspelling](https://facelessuser.github.io/pyspelling/). - -It can then be run with the following command: - -```console -pyspelling -c spellcheck.yml -``` - -Words that should be ignored or are unrecognized must be added to the [wordlist](./wordlist.txt). - -### Markdown Verification - -We use [remark](https://remark.js.org/) to verify our markdown. You can easily run this tool simply by using our `npm` package: - -```console -npm install -npm run lint -``` +Become familiar with the [specification style guidelines](STYLE-GUIDELINE.md) to understand how you should write or amend specifications. ## Spec lifecycle diff --git a/STYLE-GUIDELINE.md b/STYLE-GUIDELINE.md new file mode 100644 index 0000000..3052da0 --- /dev/null +++ b/STYLE-GUIDELINE.md @@ -0,0 +1,94 @@ +--- +layout: default +permalink: /style-guideline +title: STYLE-GUIDELINE +--- + +# Style guidelines for Status client specifications + +- [Spellcheck](#spellcheck) +- [Markdown Verification](#markdown-verification) +- [Language Mode](#language-mode) + +## Spellcheck + +To run the spellchecker locally, you must install [pyspelling](https://facelessuser.github.io/pyspelling/). + +It can then be run with the following command: + +```console +pyspelling -c spellcheck.yml +``` + +Words that should be ignored or are unrecognized must be added to the [wordlist](./wordlist.txt). + +## Markdown Verification + +We use [remark](https://remark.js.org/) to verify our markdown. You can easily run this tool simply by using our `npm` package: + +```console +npm install +npm run lint +``` + +## Language mode + +- Specifications SHOULD use formal technical language (*different from academic language*). +- Where appropriate, language SHOULD NOT use personal pronouns. +- Avoid using the [passive voice](https://en.wikipedia.org/wiki/English_passive_voice) when being specific. +- In places where the passive voice is appropriate but makes the subject ambiguous, append the passive voice with "by `subject`". Alternatively restructure the sentence to be in the active voice adding the sentence subject. + +For further reading on writing technical documents please read the Google Technical Writing article on [Active voice vs. passive voice](https://developers.google.com/tech-writing/one/active-voice). + +
+Examples: + +### Personal pronouns + +Informal: +>In this specification, **we** describe + +Formal: +>This specification describes + +Informal: +>If **you** want to run a Waku node and receive messages from Status clients, it must be properly configured. + +Formal: +>A Waku node must be properly configured to receive messages from Status clients. + +### Passive voice + +Passive voice: +>a corresponding confirmation **is broadcast** by one or more peers + +Active voice: +>**one or more peers broadcast** a corresponding confirmation + +In the case where the object of the sentence needs to be highlighted or given prominence the passive voice is appropriate. +However, pay attention to not introduce an ambiguous subject if communicating specific information is your goal. + +### Appropriate use of the passive voice + +>The Batch Acknowledge packet is followed by a keccak256 hash of the envelope's batch data (raw bytes). + +The subject of the sentence is "a keccak256 hash", but the sentence wants to highlight the Batch Acknowledge. + +### Ambiguous subject + +In many cases sentences written in passive voice may be grammatically correct but hide that the sentence lacks a specified subject. + +Ambiguous: +>A message confirmation **is sent** using Batch Acknowledge + +Active specific: +>**A node sends** a message confirmation using Batch Acknowledge + +Passive specific: +>A message confirmation **is sent by a node** using Batch Acknowledge + +Notice that the ambiguous sentence infers or omits the subject. Making it unclear what or who performs an action on the object of the sentence. + +In the example ambiguous sentence it is not stated what or who is sending a message confirmation. + +
diff --git a/docs/draft/12-sticker-pack.md b/docs/draft/12-sticker-pack.md index 93b4378..d1fd838 100644 --- a/docs/draft/12-sticker-pack.md +++ b/docs/draft/12-sticker-pack.md @@ -22,8 +22,8 @@ title: 12/IPFS gateway for Sticker Pack ## Abstract -In this specification, we describe how Status uses the IPFS gateway to store stickers. -We will explore image format, how they are uploaded and how an end user can see them inside the Status app. +This specification describes how Status uses the IPFS gateway to store stickers. +The specification explores image format, how a user uploads stickers and how an end user can see them inside the Status app. ## Definition @@ -41,25 +41,25 @@ The minimum sticker image resolution is 512x512, and its background SHOULD be tr ### Distribution -Sticker packs are implemented as [ERC721 token](https://eips.ethereum.org/EIPS/eip-721) and contain a set of stickers. These stickers -are stored inside the sticker pack as a set of hyperlinks pointing to IPFS storage. These hyperlinks are publicly available and can be accessed by any user inside the status chat. +The node implements sticker packs as [ERC721 token](https://eips.ethereum.org/EIPS/eip-721) and contain a set of stickers. The node stores these stickers +inside the sticker pack as a set of hyperlinks pointing to IPFS storage. These hyperlinks are publicly available and can be accessed by any user inside the status chat. Stickers can be sent in chat only by accounts that own the sticker pack. ### IPFS gateway At the moment of writing, the current main Status app uses the [Infura](https://infura.io/) gateway. However, clients could choose a different gateway or to run own IPFS node. Infura gateway is an HTTPS gateway, which based on an HTTP GET request with the multihash block will return the stored content at that block address. -The use of gateway is required to enable easy access to the resources over HTTP. -Each image of a sticker is stored inside IPFS using a unique address that is +The node requires the use of a gateway to enable easy access to the resources over HTTP. +The node stores each image of a sticker inside IPFS using a unique address that is derived from the hash of the file. This ensures that a file can't be overridden, and an end-user of the IPFS will receive the same file at a given address. ### Security The IPFS gateway acts as an end-user of the IPFS and allows users of the gateway to access IPFS without connection to the P2P network. Usage of a gateway introduces potential risk for the users of that gateway provider. In case of a compromise in the security of the provider, meta information such as IP address, User-Agent and other of its users can be leaked. -If the provider servers are unavailable the access trough gateway to the IPFS network is lost. +If the provider servers are unavailable the node loses access through the gateway to the IPFS network. ### Status sticker usage -When a sticker is shown in the app, Status app makes an http GET request to IPFS gateway using the hyperlink. +When the app shows a sticker, the Status app makes an HTTP GET request to IPFS gateway using the hyperlink. To send a sticker in chat, a user of Status should buy or install a sticker pack. @@ -76,25 +76,25 @@ To submit a sticker pack, the author should upload all assets to IPFS. Then gene :stickers [{:hash "e301017012207737b75367b8068e5bdd027d7b71a25138c83e155d1f0c9bc5c48ff158724495"} {:hash "e301017012201a9cdea03f27cda1aede7315f79579e160c7b2b6a2eb51a66e47a96f47fe5284"}]}} ``` -All assets fields, are contenthash fields as per [EIP 1577](https://eips.ethereum.org/EIPS/eip-1577). - This payload is uploaded also to IPFS, and the IPFS address is used in the content field of the Sticker Market contract. See [Sticker Market spec](https://github.com/status-im/sticker-market/blob/651e88e5f38c690e57ecaad47f46b9641b8b1e27/docs/specification.md) for a detailed description of the contract. +All asset fields, are contenthash fields as per [EIP 1577](https://eips.ethereum.org/EIPS/eip-1577). +The node also uploads this payload to IPFS, and the node uses the IPFS address in the content field of the Sticker Market contract. See [Sticker Market spec](https://github.com/status-im/sticker-market/blob/651e88e5f38c690e57ecaad47f46b9641b8b1e27/docs/specification.md) for a detailed description of the contract. #### Install a sticker pack -To install a sticker pack, we need to fetch all sticker packs which are available in Sticker Market. The following steps are needed to fetch all sticker packs: +To install a sticker pack, the node fetches all sticker packs available in Sticker Market. The node needs the following steps to fetch all sticker packs: #### 1. Get total number of sticker packs Call `packCount()` on the sticker market contract, will return number of sticker pack registered as `uint256`. #### 2. Get sticker pack by id -ID's are represented as `uint256` and are incremental from `0` to total number of sticker packs in contract, which we received on previous step. To get a sticker pack we should call `getPackData(sticker-pack-id)`, the return type is `["bytes4[]" "address" "bool" "uint256" "uint256" "bytes"]` which represents the following fields: `[category owner mintable timestamp price contenthash]`. Price is the SNT value in wei set by sticker pack owner. The contenthash is the IPFS address described in the [submit description](#submit-a-sticker) above. Other fields specification could be found in [Sticker Market spec](https://github.com/status-im/sticker-market/blob/651e88e5f38c690e57ecaad47f46b9641b8b1e27/docs/specification.md) +ID's are represented as `uint256` and are incremental from `0` to total number of sticker packs in the contract, received in the previous step. To get a sticker pack call `getPackData(sticker-pack-id)`, the return type is `["bytes4[]" "address" "bool" "uint256" "uint256" "bytes"]` which represents the following fields: `[category owner mintable timestamp price contenthash]`. Price is the SNT value in wei set by sticker pack owner. The contenthash is the IPFS address described in the [submit description](#submit-a-sticker) above. Other fields specification could be found in [Sticker Market spec](https://github.com/status-im/sticker-market/blob/651e88e5f38c690e57ecaad47f46b9641b8b1e27/docs/specification.md) ##### 3. Get owned sticker packs -The current Status app fetches owned sticker packs during the open of any sticker view (a screen which shows a sticker pack or the list of sticker packs). -To get owned packs, we should get all owned tokens for the current account address. To do that we should call `balanceOf(address)` where address is the address for current account. This method returns a `uint256` representing the count of available tokens. Using `tokenOfOwnerByIndex(address,uint256)` method, with the address of the user and ID in form of a `uint256` which is an incremented int from 0 to total number of tokens, we will get token id. To get sticker pack id from token we call`tokenPackId(uint256)` where `uint256` is the token id. This method will return an `uint256` which is the id of the owned sticker pack. +The current Status app fetches owned sticker packs during the open of any sticker view (a screen which shows a sticker pack, or the list of sticker packs). +To get owned packs, get all owned tokens for the current account address, by calling `balanceOf(address)` where address is the address for the current account. This method returns a `uint256` representing the count of available tokens. Using `tokenOfOwnerByIndex(address,uint256)` method, with the address of the user and ID in form of a `uint256` which is an incremented int from 0 to the total number of tokens, gives the token id. To get the sticker pack id from a token call`tokenPackId(uint256)` where `uint256` is the token id. This method will return an `uint256` which is the id of the owned sticker pack. ##### 4. Buy a sticker pack -To buy a sticker pack we should call `approveAndCall(address,uint256,bytes)` where `address` is the address of buyer,`uint256` is the price and third parameters `bytes` is the callback called if approved. In callback we call `buyToken(uint256,address,uint256)`, first parameter is sticker pack id, second buyers address, and the last is the price. +To buy a sticker pack call `approveAndCall(address,uint256,bytes)` where `address` is the address of buyer,`uint256` is the price and third parameters `bytes` is the callback called if approved. In the callback, call `buyToken(uint256,address,uint256)`, first parameter is sticker pack id, second buyers address, and the last is the price. ## Copyright diff --git a/docs/draft/13-3rd-party.md b/docs/draft/13-3rd-party.md index d15a086..c366a6d 100644 --- a/docs/draft/13-3rd-party.md +++ b/docs/draft/13-3rd-party.md @@ -31,7 +31,7 @@ title: 13/3RD-PARTY-USAGE ## Abstract -In this specification, we discuss 3rd party APIs that Status relies on. These APIs provide various capabilities such as: +This specification discusses 3rd party APIs that Status relies on. These APIs provide various capabilities such as: - communicate with the Ethereum network - allow users to see address and transaction details on external website - get fiat/crypto exchange rates @@ -48,7 +48,7 @@ In this specification, we discuss 3rd party APIs that Status relies on. These AP ## Why 3rd party API can be a problem? -Relying on 3rd party APIs interferes with `censorship resistance` Status principle. Since we aim to avoid suppression of information it is important to reduce amount of 3rd parties crucial for app functionality. +Relying on 3rd party APIs interferes with `censorship resistance` Status principle. Since Status aims to avoid suppression of information it is important to reduce amount of 3rd parties crucial for app functionality. ## 3rd party APIs used by current Status app @@ -61,7 +61,7 @@ Infura hosts a collection of full nodes for the Ethereum network and provides an Status works on mobile devices and therefore can't rely on local node. So all communication to Ethereum network happens via Infura. ##### Concerns -Making http request means that a user leaks metadata, which can be used in various attacks if the service is hacked. +Making a HTTP request means that a user leaks metadata, which can be used in various attacks if an attacker hacks the service. Infura hosts on centralized providers. If these fail or the provider cuts off service, then Status features requiring Ethereum calls will. @@ -84,7 +84,7 @@ CryptoCompare is a service that shows live streaming prices, charts and analysis Status regularly fetches crypto prices from CryptoCompare. Using that info Status calculates fiat value for transaction or wallet assets. ##### Concerns -Making http request means that a user leaks metadata, which can be used in various attacks if the service is hacked. +Making a HTTP request means that a user leaks metadata, which can be used in various attacks if an attacker hacks the service. If CryptoCompare fails Status won't be able to show fiat equivalent of crypto in wallet. ### Collectibles @@ -97,7 +97,7 @@ There is a set of services that used for getting information about collectibles: ##### Concerns -Making http request means that a user leaks metadata, which can be used in various attacks if the service is hacked. +Making a HTTP request means that a user leaks metadata, which can be used in various attacks if an attacker hacks the service. ### Iubenda diff --git a/docs/draft/3-whisper-usage.md b/docs/draft/3-whisper-usage.md index 789f6f5..114ebdd 100644 --- a/docs/draft/3-whisper-usage.md +++ b/docs/draft/3-whisper-usage.md @@ -37,15 +37,13 @@ Status uses [Whisper](https://eips.ethereum.org/EIPS/eip-627) to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. -This allows allows anyone to listen on a single channel. +This allows anyone to listen on a single channel. Additionally, since anyone can receive Whisper envelopes, it relies on the -ability to decrypt messages to decide who is the correct recipient. We do -however not rely on this property, but instead implement another secure -transport layer on top of Whisper. +ability to decrypt messages to decide who is the correct recipient. Status nodes do not +rely upon this property, and implement another secure transport layer on top of Whisper. -Finally, we use an extension of Whisper to provide the ability to do offline -messaging. +Finally, using an extension of Whisper provides the ability to do offline messaging. ## Reason @@ -56,9 +54,9 @@ encryption properties to support asynchronous chat. * *Whisper node*: an Ethereum node with Whisper V6 enabled (in the case of geth, it's `--shh` option) * *Whisper network*: a group of Whisper nodes connected together through the internet connection and forming a graph -* *Message*: decrypted Whisper message +* *Message*: a decrypted Whisper message * *Offline message*: an archived envelope -* *Envelope*: encrypted message with metadata like topic and Time-To-Live +* *Envelope*: an encrypted message with metadata like topic and Time-To-Live ## Whisper packets @@ -79,7 +77,7 @@ encryption properties to support asynchronous chat. ## Whisper node configuration -If you want to run a Whisper node and receive messages from Status clients, it must be properly configured. +A Whisper node must be properly configured to receive messages from Status clients. Whisper's Proof Of Work algorithm is used to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status' main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: * proof-of-work requirement not larger than `0.00001` @@ -100,7 +98,7 @@ Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start `confirmationsEnabled`: when true, the peer will send message confirmations `rateLimits`: is `[ RateLimitIP, RateLimitPeerID, RateLimitTopic ]` where each values is an integer with a number of accepted packets per second per IP, Peer ID, and Topic respectively -`bloom, isLightNode, confirmationsEnabled, and rateLimits` are all optional arguments in the handshake. However, if you specify optional field you MUST also specify all optional fields preceding it, in order to be unambiguous. +`bloom, isLightNode, confirmationsEnabled, and rateLimits` are all optional arguments in the handshake. However, if an optional field is specified, all optional fields preceding it MUST also be specified in order to be unambiguous. ## Rate limiting @@ -130,7 +128,7 @@ The protocol requires a key (symmetric or asymmetric) for the following actions: * signing & verifying messages (asymmetric key) * encrypting & decrypting messages (asymmetric or symmetric key). -As asymmetric keys and symmetric keys are required to process incoming messages, +As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory. Keys management for PFS is described in [5/SECURE-TRANSPORT](https://specs.status.im/spec/5). @@ -139,7 +137,7 @@ The Status protocols uses a few particular Whisper topics to achieve its goals. ### Contact code topic -Contact code topic is used to facilitate the discovery of X3DH bundles so that the first message can be PFS-encrypted. +Nodes use the contact code topic to facilitate the discovery of X3DH bundles so that the first message can be PFS-encrypted. Each user publishes periodically to this topic. If user A wants to contact user B, she SHOULD look for their bundle on this contact code topic. @@ -164,9 +162,9 @@ for i = 0; i < topicLen; i++ { Whisper is broadcast-based protocol. In theory, everyone could communicate using a single topic but that would be extremely inefficient. Opposite would be using a unique topic for each conversation, however, this brings privacy concerns because it would be much easier to detect whether and when two parties have an active conversation. -Partitioned topics are used to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. +Nodes use partitioned topics to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. -Currently, the number of partitioned topics is set to `5000`. They MUST be generated following the algorithm below: +Currently, nodes set the number of partitioned topics to `5000`. Partitioned topics MUST be generated following the algorithm below: ```golang var partitionsNum *big.Int = big.NewInt(5000) var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum) @@ -272,20 +270,20 @@ A client SHOULD send to the negotiated topic only if it has received a message f ### Flow -To exchange messages with client B, a client A SHOULD: +To exchange messages with client `B`, a client `A` SHOULD: -- Listen to client's B Contact Code Topic to retrieve their bundle information, including a list of active devices -- Send a message on client's B partitioned topic -- Listen to the Negotiated Topic between A & B -- Once a message is received from B, the Negotiated Topic SHOULD be used +- Listen to client's `B` Contact Code Topic to retrieve their bundle information, including a list of active devices +- Send a message on client's `B` partitioned topic +- Listen to the Negotiated Topic between `A` & `B` +- Once client `A` receives a message from `B`, the Negotiated Topic SHOULD be used ## Message encryption Even though, the protocol specifies an encryption layer that encrypts messages before passing them to the transport layer, Whisper protocol requires each Whisper message to be encrypted anyway. -Public and group messages are encrypted using symmetric encryption and the key is created from a channel name string. The implementation is available in [`shh_generateSymKeyFromPassword`](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_generatesymkeyfrompassword) JSON-RPC method of go-ethereum Whisper implementation. +The node encrypts public and group messages using symmetric encryption, and creates the key from a channel name string. The implementation is available in [`shh_generateSymKeyFromPassword`](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_generatesymkeyfrompassword) JSON-RPC method of go-ethereum Whisper implementation. -One-to-one messages are encrypted using asymmetric encryption. +The node encrypts one-to-one messages using asymmetric encryption. ## Message confirmations @@ -293,7 +291,7 @@ Sending a message is a complex process where many things can go wrong. Message c A node MAY send a message confirmation for any batch of messages received in a packet Messages Code (`0x01`). -A message confirmation is sent using Batch Acknowledge packet (`0x0b`) or Message Response packet (`0x0c`). +A node sends a message confirmation using Batch Acknowledge packet (`0x0b`) or Message Response packet (`0x0c`). The Batch Acknowledge packet is followed by a keccak256 hash of the envelopes batch data (raw bytes). @@ -308,7 +306,7 @@ The Message Response packet is more complex and is followed by a Versioned Messa The supported codes: `1`: means time sync error which happens when an envelope is too old or created in the future (the root cause is no time sync between nodes). -The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, a corresponding confirmation is broadcast by one or more peers. To limit that, both Batch Acknowledge packet (`0x0b`) and Message Response packet (`0x0c`) are not broadcast to peers of the peers, i.e. they do not follow epidemic spread. +The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, one or more peers broadcast a corresponding confirmation. To limit that, both Batch Acknowledge packet (`0x0b`) and Message Response packet (`0x0c`) are not broadcast to peers of the peers, i.e. they do not follow epidemic spread. In the current Status network setup, only Mailservers support message confirmations. A client posting a message to the network and after receiving a confirmation can be sure that the message got processed by the Mailserver. If additionally, sending a message is limited to non-Mailserver peers, it also guarantees that the message got broadcast through the network and it reached the selected Mailserver. diff --git a/docs/draft/6-payloads.md b/docs/draft/6-payloads.md index 97744d4..e220446 100644 --- a/docs/draft/6-payloads.md +++ b/docs/draft/6-payloads.md @@ -14,7 +14,7 @@ title: 6/PAYLOADS ## Abstract -This specifications describes how the payload of each message in Status looks +This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases. The payloads aims to be flexible enough to support messaging but also cases @@ -53,7 +53,7 @@ as various clients created using different technologies. ## Introduction -In this document we describe the payload format and some special considerations. +This document describes the payload format and some special considerations. ## Payload wrapper @@ -68,12 +68,12 @@ message StatusProtocolMessage { ``` `signature` is the bytes of the signed `SHA3-256` of the payload, signed with the key of the author of the message. -The signature is needed 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. +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. ## Encoding -The payload is encoded using [Protobuf](https://developers.google.com/protocol-buffers) +The node encodes the payload using [Protobuf](https://developers.google.com/protocol-buffers) ## Types of messages @@ -148,12 +148,12 @@ message ChatMessage { #### Content types -Content types are required for a proper interpretation of incoming messages. Not each message is plain text but may carry a different information. +A node requires content types for a proper interpretation of incoming messages. Not each message is plain text but may carry different information. The following content types MUST be supported: * `TEXT_PLAIN` identifies a message which content is a plaintext. -There are also other content types that MAY be implemented by the client: +There are other content types that MAY be implemented by the client: * `STICKER` * `STATUS` * `EMOJI` @@ -193,7 +193,7 @@ message ImageMessage { #### Message types -Message types are required to decide how a particular message is encrypted and what metadata needs to be attached when passing a message to the transport layer. For more on this, see [3/WHISPER-USAGE](https://specs.status.im/spec/3). +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 [3/WHISPER-USAGE](./../stable/3-whisper-usage.md) and [10/WAKU-USAGE](./../stable/10-waku-usage.md). @@ -214,28 +214,28 @@ Lamport timestamp format is: `clock = `max({timestamp}, chat_clock + 1)` This will satisfy the Lamport requirement, namely: a -> b then T(a) < T(b) -`timestamp` MUST be Unix time calculated when the message is created in milliseconds. This field SHOULD not be relied upon for message ordering. +`timestamp` MUST be Unix time calculated, when the node creates the message, in milliseconds. This field SHOULD not be relied upon for message ordering. -`clock` SHOULD be calculated using the algorithm of [Lamport timestamps](https://en.wikipedia.org/wiki/Lamport_timestamps). When there are messages available in a chat, `clock`'s value is calculated based on the last received message in a particular chat: `max(timeNowInMs, last-message-clock-value + 1)`. If there are no messages, `clock` is initialized with `timestamp`'s value. +`clock` SHOULD be calculated using the algorithm of [Lamport timestamps](https://en.wikipedia.org/wiki/Lamport_timestamps). When there are messages available in a chat, the node calculates `clock`'s value based on the last received message in a particular chat: `max(timeNowInMs, last-message-clock-value + 1)`. If there are no messages, `clock` is initialized with `timestamp`'s value. Messages with a `clock` greater than `120` seconds over the whisper timestamp SHOULD be discarded, in order to avoid malicious users to increase the `clock` of a chat arbitrarily. Messages with a `clock` less than `120` seconds under the whisper timestamp might indicate an attempt to insert messages in the chat history which is not distinguishable from a `datasync` layer re-transit event. A client MAY mark this messages with a warning to the user, or discard them. -`clock` value is used for the message ordering. Due to the used algorithm and distributed nature of the system, we achieve casual ordering which might produce counter-intuitive results in some edge cases. For example, when one joins a public chat and sends a message before receiving the exist messages, their message `clock` value might be lower and the message will end up in the past when the historical messages are fetched. +The node uses `clock` 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 `clock` value might be lower and the message will end up in the past when the historical messages are fetched. #### Chats -Chat is a structure that helps organize messages. It's usually desired to display messages only from a single recipient or a group of recipients at a time and chats help to achieve that. +Chat is a structure that helps organize messages. It's usually desired to display messages only from a single recipient, or a group of recipients at a time and chats help to achieve that. -All incoming messages can be matched against a chat. Below you can find a table that describes how to calculate a chat ID for each message type. +All incoming messages can be matched against a chat. The below table describes how to calculate a chat ID for each message type. |Message Type|Chat ID Calculation|Direction|Comment| |------------|-------------------|---------|-------| |PUBLIC_GROUP|chat ID is equal to a public channel name; it should equal `chatId` from the message|Incoming/Outgoing|| |ONE_TO_ONE|let `P` be a public key of the recipient; `hex-encode(P)` is a chat ID; use it as `chatId` value in the message|Outgoing|| -|user-message|let `P` be a public key of message's signature; `hex-encode(P)` is a chat ID; discard `chat-id` from message|Incoming|if there is no matched chat, it might be the first message from public key `P`; you can discard it or create a new chat; Status official clients create a new chat| -|PRIVATE_GROUP|use `chatId` from the message|Incoming/Outgoing|find an existing chat by `chatId`; if none is found, we are not a member of that chat or we haven't joined that chat, the message MUST be discarded | +|user-message|let `P` be a public key of message's signature; `hex-encode(P)` is a chat ID; discard `chat-id` from message|Incoming|if there is no matched chat, it might be the first message from public key `P`; the node MAY discard the message or MAY create a new chat; Status official clients create a new chat| +|PRIVATE_GROUP|use `chatId` from the message|Incoming/Outgoing|find an existing chat by `chatId`; if none is found, the user is not a member of that chat or the user hasn't joined that chat, the message MUST be discarded | ### Contact Update @@ -264,13 +264,13 @@ message ContactUpdate { A client SHOULD send a `ContactUpdate` to all the contacts each time: - The ens_name has changed -- The profile image is edited +- A user edits the profile image A client SHOULD also periodically send a `ContactUpdate` to all the contacts, the interval is up to the client, the Status official client sends these updates every 48 hours. ### SyncInstallationContact -`SyncInstallationContact` messages are used to synchronize in a best-effort the contacts to other devices. +The node uses `SyncInstallationContact` messages to synchronize in a best-effort the contacts to other devices. ```protobuf message SyncInstallationContact { @@ -296,7 +296,7 @@ message SyncInstallationContact { ### SyncInstallationPublicChat -`SyncInstallationPublicChat` message is used to synchronize in a best-effort the public chats to other devices. +The node uses `SyncInstallationPublicChat` message to synchronize in a best-effort the public chats to other devices. ```protobuf message SyncInstallationPublicChat { @@ -314,7 +314,7 @@ message SyncInstallationPublicChat { ### PairInstallation -`PairInstallation` messages are used to propagate information about a device to its paired devices. +The node uses `PairInstallation` messages to propagate information about a device to its paired devices. ```protobuf message PairInstallation { @@ -337,14 +337,14 @@ message PairInstallation { ### MembershipUpdateMessage and MembershipUpdateEvent `MembershipUpdateEvent` is a message used to propagate information about group membership changes in a group chat. -The details are in the [Group chats specs](./7-group-chat.md) +The details are in the [Group chats specs](./7-group-chat.md). ## Upgradability There are two ways to upgrade the protocol without breaking compatibility: -- Accretion is always supported -- Deletion of existing fields or messages is not supported and might break compatibility +- A node always supports accretion +- A node does not support deletion of existing fields or messages, which might break compatibility ## Security Considerations diff --git a/docs/draft/7-group-chat.md b/docs/draft/7-group-chat.md index be6d31f..46a876a 100644 --- a/docs/draft/7-group-chat.md +++ b/docs/draft/7-group-chat.md @@ -31,11 +31,11 @@ title: 7/GROUP-CHAT ## Abstract -This documents describes the group chat protocol used by the status application. Pairwise encryption is used among member so a message is exchanged between each participants, similarly to a one-to-one message. +This document describes the group chat protocol used by the status application. The node uses pairwise encryption among member so a message is exchanged between each participant, similarly to a one-to-one message. ## Membership updates -Membership updates messages are used to propagate group chat membership changes. The protobuf format is described in the [6/PAYLOADS](https://specs.status.im/spec/6). Here we will be describing each specific field. +The node uses membership updates messages to propagate group chat membership changes. The protobuf format is described in the [6/PAYLOADS](https://specs.status.im/spec/6). Below describes each specific field. The protobuf messages are: @@ -102,47 +102,47 @@ The format of this chat ID MUST be a string of [UUID](https://tools.ietf.org/htm ### Signature -The signature for each event is calculated by encoding each `MembershipUpdateEvent` in its protobuf representation and prepending the bytes of the chatID, lastly the `Keccak256` of the bytes is signed using the private key by the author and added to the `events` field of MembershipUpdateMessage. +The node calculates the signature for each event by encoding each `MembershipUpdateEvent` in its protobuf representation and prepending the bytes of the chatID, lastly the node signs the `Keccak256` of the bytes using the private key by the author and added to the `events` field of MembershipUpdateMessage. ### Group membership event -Any group membership event received MUST be verified by calculating the signature as per the method described above. +Any `group membership` event received MUST be verified by calculating the signature as per the method described above. The author MUST be extracted from it, if the verification fails the event MUST be discarded. #### CHAT_CREATED -Chat created event is the first event that needs to be sent. Any event with a clock value lower then this MUST be discarded. +Chat `created event` is the first event that needs to be sent. Any event with a clock value lower than this MUST be discarded. Upon receiving this event a client MUST validate the `chatId` provided with the updates and create a chat with identified by `chatId` and named `name`. #### NAME_CHANGED -A name changed event is used by admins to change the name of the group chat. +`admins` use a `name changed` event to change the name of the group chat. Upon receiving this event a client MUST validate the `chatId` provided with the updates and MUST ensure the author of the event is an admin of the chat, otherwise the event MUST be ignored. If the event is valid the chat name SHOULD be changed to `name`. #### MEMBERS_ADDED -A members added event is used by admins to add members to the chat. +`admins` use a `members added` event to add members to the chat. Upon receiving this event a client MUST validate the `chatId` provided with the updates and MUST ensure the author of the event is an admin of the chat, otherwise the event MUST be ignored. If the event is valid a client MUST update the list of members of the chat who have not joined, adding the `members` received. `members` is an array of hex encoded public keys. #### MEMBER_JOINED -A members joined event is used by a member of the chat to signal that they want to start receiving messages from this chat. +`members` use a `members joined` event to signal that they want to start receiving messages from this chat. Upon receiving this event a client MUST validate the `chatId` provided with the updates. If the event is valid a client MUST update the list of members of the chat who joined, adding the signer. Any `message` sent to the group chat should now include the newly joined member. #### ADMINS_ADDED -An admins added event is used by admins to add make other admins in the chat. +`admins` use an `admins added` event to add make other admins in the chat. Upon receiving this event a client MUST validate the `chatId` provided with the updates, MUST ensure the author of the event is an admin of the chat and MUST ensure all `members` are already `members` of the chat, otherwise the event MUST be ignored. If the event is valid a client MUST update the list of admins of the chat, adding the `members` received. `members` is an array of hex encoded public keys. #### MEMBER_REMOVED -A member-removed event is used to leave or kick members of the chat. +`members` and/or `admins` use a `member-removed` event to leave or kick members of the chat. Upon receiving this event a client MUST validate the `chatId` provided with the updates, MUST ensure that: - If the author of the event is an admin, target can only be themselves or a non-admin member. - If the author of the event is not an admin, the target of the event can only be themselves. @@ -151,7 +151,7 @@ If the event is valid a client MUST remove the member from the list of `members` #### ADMIN_REMOVED -An admin-removed event is used to drop admin privileges. +`Admins` use an `admin-removed` event to drop admin privileges. Upon receiving this event a client MUST validate the `chatId` provided with the updates, MUST ensure that the author of the event is also the target of the event. If the event is valid a client MUST remove the member from the list of `admins` of the chat. diff --git a/docs/stable/1-client.md b/docs/stable/1-client.md index bd9c9a8..3eb6db5 100644 --- a/docs/stable/1-client.md +++ b/docs/stable/1-client.md @@ -14,10 +14,10 @@ title: 1/CLIENT ## Abstract -In this specification, we describe how to write a Status client for +This specification describes how to write a Status client for communicating with other Status clients. -We present a reference implementation of the protocol 1 that is used +This specification presents a reference implementation of the protocol 1 that is used in a command line client 2 and a mobile app 3. This document consists of two parts. The first outlines the specifications that @@ -69,7 +69,7 @@ have to be implemented in order to be a full Status client. The second gives a d Implementing a Status clients largely means implementing the following layers. Additionally, there are separate specifications for things like key management and account lifecycle. -Other aspects, such as how IPFS is used for stickers, how we interact with the Ethereum blockchain or how the browser works, are currently underspecified. These sets of specifications should allow you to implement a a Status client for basic private communication. +Other aspects, such as how a node uses IPFS for stickers or how the browser works, are currently underspecified. These specifications facilitate the implementation of a Status client for basic private communication. | Layer | Purpose | Technology | | ----------------- | ------------------------------ | ---------------------------- | @@ -81,7 +81,7 @@ Other aspects, such as how IPFS is used for stickers, how we interact with the E ### Protobuf -We use [`protobuf`](https://developers.google.com/protocol-buffers/) in different layers, the version used is `proto3` unless stated otherwise. +[`protobuf`](https://developers.google.com/protocol-buffers/) is used in different layers, version `proto3` used is unless stated otherwise. ## Components @@ -97,7 +97,7 @@ To communicate between Status nodes, the [RLPx Transport Protocol, v5](https://github.com/ethereum/devp2p/blob/master/rlpx.md) is used, which allows for TCP-based communication between nodes. -On top of this we run RLPx-based subprotocols, the client +On top of this RLPx-based subprotocols are ran, the client SHOULD NOT use [Whisper V6](https://eips.ethereum.org/EIPS/eip-627), the client SHOULD use [Waku V1](https://github.com/vacp2p/specs/blob/master/specs/waku/waku-1.md) for privacy-preserving messaging and efficient usage of a node's bandwidth. @@ -116,10 +116,10 @@ client mode, otherwise the user experience is likely to be poor. #### Bootstrapping -To connect to other Status nodes you need to connect to a bootstrap node. These -nodes allow you to discover other nodes of the network. +Bootstrap nodes allow Status nodes to discover and connect to other Status nodes +in the network. -Currently the main bootstrap nodes are provided by Status Gmbh, but anyone can +Currently, Status Gmbh provides the main bootstrap nodes, but anyone can run these provided they are connected to the rest of the Whisper/Waku network. Status maintains a list of production fleet bootstrap nodes in the following locations: @@ -139,12 +139,12 @@ Status maintains a list of production fleet bootstrap nodes in the following loc - `enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443` - `enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443` -These bootstrap nodes MAY change and we can't guarantee that it will stay this way forever -and at some point we might be forced to change them. +These bootstrap nodes MAY change and are not guaranteed to stay this way forever +and at some point circumstances might force them to change. #### Discovery -To implement a Status client you MUST discover or have a list of peers to connect to. We use a +A Status client MUST discover or have a list of peers to connect to. Status uses a light discovery mechanism based on a combination of [Discovery v5](https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md) and [Rendezvous Protocol](https://github.com/libp2p/specs/tree/master/rendezvous), @@ -183,7 +183,7 @@ when the client starts again. In such a case, there might be no need to even sta peers discovery protocols because cached peers will satisfy the optimal number of peers. Alternatively, a client MAY rely exclusively on a list of static peers. This is the most efficient -way because there is no peers discovery algorithm overhead introduced. The disadvantage +way because there are no peers discovery algorithm overhead introduced. The disadvantage is that these peers might be gone and without peers discovery mechanism, it won't be possible to find new ones. @@ -211,7 +211,7 @@ For providing an offline inbox, see the complementary [4/WHISPER-MAILSERVER](htt ### Secure Transport In order to provide confidentiality, integrity, authentication and forward -secrecy of messages we implement a secure transport on top of Whisper and Waku. This is +secrecy of messages the node implements a secure transport on top of Whisper and Waku. This is used in 1:1 chats and group chats, but not for public chats. See [5/SECURE-TRANSPORT](https://specs.status.im/spec/5) for more. ### Data Sync @@ -219,13 +219,13 @@ used in 1:1 chats and group chats, but not for public chats. See [5/SECURE-TRANS [MVDS](https://specs.vac.dev/mvds.html) is used for 1:1 and group chats, however it is currently not in use for public chats. [Status payloads](#payloads-and-clients) are serialized and then wrapped inside an MVDS message which is added to an [MVDS payload](https://specs.vac.dev/mvds.html#payloads), -this payload is then encrypted (if necessary for 1-to-1 / group-chats) and sent using +the node encrypts this payload (if necessary for 1-to-1 / group-chats) and sends it using Whisper or Waku which also encrypts it. ### Payloads and clients -On top of secure transport, we have various types of data sync clients and -payload formats for things like 1:1 chat, group chat and public chat. These have +On top of secure transport, various types of data sync clients and +the node uses payload formats for things like 1:1 chat, group chat and public chat. These have various degrees of standardization. Please refer to [6/PAYLOADS](https://specs.status.im/spec/6) for more details. ### BIPs and EIPs Standards support @@ -243,8 +243,8 @@ See [Appendix A](#appendix-a-security-considerations) #### Why devp2p? Why not use libp2p? -At the time the main Status clients were being developed, devp2p was the most -mature. However, it is likely we'll move over to libp2p in the future, as it'll +At the time Status developed the main Status clients, devp2p was the most +mature. However, in the future libp2p is likely to be used, as it'll provide us with multiple transports, better protocol negotiation, NAT traversal, etc. @@ -306,10 +306,10 @@ methods of spam protection are currently being researched. #### Why do you not use Discovery v5 for node discovery? -At the time we implemented dynamic node discovery, Discovery v5 wasn't completed +At the time of implementing dynamic node discovery, Discovery v5 wasn't completed yet. Additionally, running a DHT on a mobile leads to slow node discovery, bad battery and poor bandwidth usage. Instead, each client can choose to turn on -Discovery v5 for a short period of time until their peer list is populated. +Discovery v5 for a short period until the node populates their peer list. For some further investigation, see [here](https://github.com/status-im/swarms/blob/master/ideas/092-disc-v5-research.md). @@ -322,7 +322,7 @@ In order to use a `Mailserver`, a given node needs to connect to it directly, i. #### Why is MVDS not used for public chats? -Currently public chats are broadcast-based, and there's no direct way of finding +Currently, public chats are broadcast-based, and there's no direct way of finding out who is receiving messages. Hence there's no clear group sync state context whereby participants can sync. Additionally, MVDS is currently not optimized for large group contexts, which means bandwidth usage will be a lot higher than @@ -366,7 +366,7 @@ The main privacy concern with light nodes is that directly connected peers will **Bloom filter privacy:** -By having a bloom filter where only the topics you are interested in are set, you reveal which messages you are interested in. This is a fundamental trade-off between bandwidth usage and privacy, though the trade-off space is likely suboptimal in terms of the [Anonymity](https://eprint.iacr.org/2017/954.pdf) [trilemma](https://petsymposium.org/2019/files/hotpets/slides/coordination-helps-anonymity-slides.pdf). +A user reveals which messages they are interested in, by setting only the topics they are interested in on the bloom filter. This is a fundamental trade-off between bandwidth usage and privacy, though the trade-off space is likely suboptimal in terms of the [Anonymity](https://eprint.iacr.org/2017/954.pdf) [trilemma](https://petsymposium.org/2019/files/hotpets/slides/coordination-helps-anonymity-slides.pdf). **`Mailserver client` privacy:** @@ -378,7 +378,7 @@ Privacy for Whisper or Waku hasn't been studied rigorously for various threat mo **Topic hygiene:** -Similar to bloom filter privacy, if you use a very specific topic you reveal more information. See scalability model linked above. +Similar to bloom filter privacy, using a very specific topic reveals more information. See scalability model linked above. ### Spam resistance diff --git a/docs/stable/10-waku-usage.md b/docs/stable/10-waku-usage.md index 9e04353..42a9e65 100644 --- a/docs/stable/10-waku-usage.md +++ b/docs/stable/10-waku-usage.md @@ -43,9 +43,8 @@ the case of public chats, the channel name maps directly to its Waku topic. This allows anyone to listen on a single channel. Additionally, since anyone can receive Waku envelopes, it relies on the -ability to decrypt messages to decide who is the correct recipient. We do -however not rely on this property, but instead implement another secure -transport layer on top of Waku. +ability to decrypt messages to decide who is the correct recipient. Status nodes do not +rely upon this property, and implement another secure transport layer on top of Whisper. ## Reason @@ -56,9 +55,9 @@ encryption properties to support asynchronous chat. * *Waku node*: an Ethereum node with Waku V1 enabled * *Waku network*: a group of Waku nodes connected together through the internet connection and forming a graph -* *Message*: decrypted Waku message +* *Message*: a decrypted Waku message * *Offline message*: an archived envelope -* *Envelope*: encrypted message with metadata like topic and Time-To-Live +* *Envelope*: an encrypted message with metadata like topic and Time-To-Live ## Waku packets @@ -75,9 +74,9 @@ encryption properties to support asynchronous chat. ## Waku node configuration -If you want to run a Waku node and receive messages from Status clients, it must be properly configured. +A Waku node must be properly configured to receive messages from Status clients. -Waku's Proof Of Work algorithm is used to deter denial of service and various spam/flood attacks against the Waku network. The sender of a message must perform some work which in this case means processing time. Because Status' main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Waku node settings: +Nodes use Waku's Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status' main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: * proof-of-work requirement not larger than `0.002` for payloads less than 50,000 bytes * proof-of-work requirement not larger than `0.000002` for payloads greater than or equal to 50,000 bytes * time-to-live not lower than `10` (in seconds) @@ -135,7 +134,7 @@ The protocol requires a key (symmetric or asymmetric) for the following actions: * signing & verifying messages (asymmetric key) * encrypting & decrypting messages (asymmetric or symmetric key). -As asymmetric keys and symmetric keys are required to process incoming messages, +As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory. Keys management for PFS is described in [5/SECURE-TRANSPORT](https://specs.status.im/spec/5). @@ -144,7 +143,7 @@ The Status protocols uses a few particular Waku topics to achieve its goals. ### Contact code topic -Contact code topic is used to facilitate the discovery of X3DH bundles so that the first message can be PFS-encrypted. +Nodes use the contact code topic to facilitate the discovery of X3DH bundles so that the first message can be PFS-encrypted. Each user publishes periodically to this topic. If user A wants to contact user B, she SHOULD look for their bundle on this contact code topic. @@ -169,9 +168,9 @@ for i = 0; i < topicLen; i++ { Waku is broadcast-based protocol. In theory, everyone could communicate using a single topic but that would be extremely inefficient. Opposite would be using a unique topic for each conversation, however, this brings privacy concerns because it would be much easier to detect whether and when two parties have an active conversation. -Partitioned topics are used to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. +Nodes use partitioned topics to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. -Currently, the number of partitioned topics is set to `5000`. They MUST be generated following the algorithm below: +Currently, nodes set the number of partitioned topics to `5000`. They MUST be generated following the algorithm below: ```golang var partitionsNum *big.Int = big.NewInt(5000) var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum) @@ -270,20 +269,20 @@ A client SHOULD send to the negotiated topic only if it has received a message f ### Flow -To exchange messages with client B, a client A SHOULD: +To exchange messages with client `B`, a client `A` SHOULD: -- Listen to client's B Contact Code Topic to retrieve their bundle information, including a list of active devices -- Send a message on client's B partitioned topic -- Listen to the Negotiated Topic between A & B -- Once a message is received from B, the Negotiated Topic SHOULD be used +- Listen to client's `B` Contact Code Topic to retrieve their bundle information, including a list of active devices +- Send a message on client's `B` partitioned topic +- Listen to the Negotiated Topic between `A` & `B` +- Once client `A` receives a message from `B`, the Negotiated Topic SHOULD be used ## Message encryption Even though, the protocol specifies an encryption layer that encrypts messages before passing them to the transport layer, Waku protocol requires each Waku message to be encrypted anyway. -Public and group messages are encrypted using symmetric encryption and the key is created from a channel name string. The implementation is available in [`waku_generateSymKeyFromPassword`](https://github.com/status-im/status-go/tree/develop/_examples) JSON-RPC method of go-ethereum Whisper implementation. +The node encrypts public and group messages using symmetric encryption, and creates the key from a channel name string. The implementation is available in [`shh_generateSymKeyFromPassword`](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_generatesymkeyfrompassword) JSON-RPC method of go-ethereum Whisper implementation. -One-to-one messages are encrypted using asymmetric encryption. +The node encrypts one-to-one messages using asymmetric encryption. ## Message confirmations @@ -291,7 +290,7 @@ Sending a message is a complex process where many things can go wrong. Message c A node MAY send a message confirmation for any batch of messages received in a packet Messages Code (`0x01`). -A message confirmation is sent using Batch Acknowledge packet (`0x0b`) or Message Response packet (`0x0c`). +A node sends a message confirmation using Batch Acknowledge packet (`0x0b`) or Message Response packet (`0x0c`). The Batch Acknowledge packet is followed by a keccak256 hash of the envelopes batch data (raw bytes). @@ -306,7 +305,7 @@ The Message Response packet is more complex and is followed by a Versioned Messa The supported codes: `1`: means time sync error which happens when an envelope is too old or created in the future (the root cause is no time sync between nodes). -The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, a corresponding confirmation is broadcast by one or more peers. To limit that, both Batch Acknowledge packet (`0x0b`) and Message Response packet (`0x0c`) are not broadcast to peers of the peers, i.e. they do not follow epidemic spread. +The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, one or more peers broadcast a corresponding confirmation. To limit that, both Batch Acknowledge packet (`0x0b`) and Message Response packet (`0x0c`) are not broadcast to peers of the peers, i.e. they do not follow epidemic spread. In the current Status network setup, only `Mailservers` support message confirmations. A client posting a message to the network and after receiving a confirmation can be sure that the message got processed by the `Mailserver`. If additionally, sending a message is limited to non-`Mailserver` peers, it also guarantees that the message got broadcast through the network and it reached the selected `Mailserver`. diff --git a/docs/stable/11-waku-mailserver.md b/docs/stable/11-waku-mailserver.md index c71231f..60d1d36 100644 --- a/docs/stable/11-waku-mailserver.md +++ b/docs/stable/11-waku-mailserver.md @@ -70,7 +70,7 @@ The envelope MUST be encrypted with a symmetric key agreed between the requester Historic messages MUST be sent to a peer as a packet with a P2P Message code (`0x7f`) followed by an array of Waku envelopes. -In order to receive historic messages from a `Mailserver`, a node MUST trust the selected `Mailserver`, that is allow to receive packets with the P2P Message code. By default, such packets are discarded. +In order to receive historic messages from a `Mailserver`, a node MUST trust the selected `Mailserver`, that is allowed to send packets with the P2P Message code. By default, the node discards such packets. Received envelopes MUST be passed through the Waku envelope pipelines so that they are picked up by registered filters and passed to subscribers. @@ -90,7 +90,7 @@ If `Cursor` is not empty, it means that not all messages were sent due to the se ### Confidentiality -All Waku envelopes are encrypted. A `Mailserver` node can not inspect their contents. +The node encrypts all Waku envelopes. A `Mailserver` node can not inspect their contents. ### Altruistic and centralized operator risk @@ -98,7 +98,7 @@ In order to be useful, a `Mailserver` SHOULD be online most of time. That means users either have to be a bit tech-savvy to run their own node, or rely on someone else to run it for them. -Currently one of Status's legal entities provides `Mailservers` in an altruistic manner, but this is +Currently, one of Status's legal entities provides `Mailservers` in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research. diff --git a/docs/stable/2-account.md b/docs/stable/2-account.md index 3dd305f..70143f9 100644 --- a/docs/stable/2-account.md +++ b/docs/stable/2-account.md @@ -14,7 +14,7 @@ title: 2/ACCOUNT ## Abstract -In this specification we explain what Status account is, and how trust is established. +This specification explains what Status account is, and how a node establishes trust. ## Table of Contents @@ -51,7 +51,7 @@ The core concept of an account in Status is a set of cryptographic keypairs. Nam 1. a Whisper/Waku chat identity keypair 1. a set of cryptocurrency wallet keypairs -Everything else associated with the contact is either verified or derived from the above items, including: +The node verifies or derives everything else associated with the contact from the above items, including: - Ethereum address (future verification, currently the same base keypair) - 3 word mnemonic name - identicon @@ -149,22 +149,22 @@ This can be done in the following ways: ``` - include BundleContainer - a new bundle SHOULD be created at least every 12 hours -- a bundle is only generated when it is used -- a bundle SHOULD be distributed on the contact code channel. This is the Whisper and Waku topic `{IK}-contact-code`, where `IK` is the hex encoded public key of the user, prefixed with `0x`. The channel is encrypted in the same way public chats are encrypted. +- a node only generates a bundle when it is used +- a bundle SHOULD be distributed on the contact code channel. This is the Whisper and Waku topic `{IK}-contact-code`, where `IK` is the hex encoded public key of the user, prefixed with `0x`. The node encrypts the channel in the same way it encrypted public chats. ### Contact Verification -Once you have the information of a contact, the following can be used to verify that the key material is as it should be. +To verify that contact key information is as it should be, use the following. #### Identicon -A low-poly identicon is deterministically generated from the Whisper/Waku chat public key. This can then be compared out of band to ensure the receiver's public key is the one you have locally. +A low-poly identicon is deterministically generated from the Whisper/Waku chat public key. This can be compared out of band to ensure the receiver's public key is the one stored locally. #### 3 word pseudonym / Whisper/Waku key fingerprint Status generates a deterministic 3-word random pseudonym from the Whisper/Waku chat public key. This pseudonym acts as a human readable fingerprint to the Whisper/Waku chat public key. This name also shows when viewing a contact's public profile and in the chat UI. - implementation: [gfycat](https://github.com/status-im/status-react/tree/develop/src/status_im/utils/gfycat) #### ENS name -Status offers the ability to register a mapping of a human readable subdomain of `stateofus.eth` to their Whisper/Waku chat public key. This registration is purchased (currently by staking 10 SNT) and stored on the Ethereum mainnet blockchain for public lookup. +Status offers the ability to register a mapping of a human readable subdomain of `stateofus.eth` to their Whisper/Waku chat public key. The user purchases this registration (currently by staking 10 SNT) and the node stores it on the Ethereum mainnet blockchain for public lookup. diff --git a/docs/stable/3-whisper-usage.md b/docs/stable/3-whisper-usage.md index 967bad8..516ad4f 100644 --- a/docs/stable/3-whisper-usage.md +++ b/docs/stable/3-whisper-usage.md @@ -39,15 +39,13 @@ Status uses [Whisper](https://eips.ethereum.org/EIPS/eip-627) to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. -This allows allows anyone to listen on a single channel. +This allows anyone to listen on a single channel. Additionally, since anyone can receive Whisper envelopes, it relies on the -ability to decrypt messages to decide who is the correct recipient. We do -however not rely on this property, but instead implement another secure -transport layer on top of Whisper. +ability to decrypt messages to decide who is the correct recipient. Status nodes do not +rely upon this property, and implement another secure transport layer on top of Whisper. -Finally, we use an extension of Whisper to provide the ability to do offline -messaging. +Finally, using an extension of Whisper provides the ability to do offline messaging. ## Reason @@ -58,9 +56,9 @@ encryption properties to support asynchronous chat. * *Whisper node*: an Ethereum node with Whisper V6 enabled (in the case of go-ethereum, it's `--shh` option) * *Whisper network*: a group of Whisper nodes connected together through the internet connection and forming a graph -* *Message*: decrypted Whisper message +* *Message*: a decrypted Whisper message * *Offline message*: an archived envelope -* *Envelope*: encrypted message with metadata like topic and Time-To-Live +* *Envelope*: an encrypted message with metadata like topic and Time-To-Live ## Whisper packets @@ -81,9 +79,9 @@ encryption properties to support asynchronous chat. ## Whisper node configuration -If you want to run a Whisper node and receive messages from Status clients, it must be properly configured. +A Whisper node must be properly configured to receive messages from Status clients. -Whisper's Proof Of Work algorithm is used to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status' main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: +Nodes use Whisper's Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status' main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: * proof-of-work requirement not larger than `0.002` * time-to-live not lower than `10` (in seconds) @@ -101,7 +99,7 @@ Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start `confirmationsEnabled`: when true, the peer will send message confirmations `rateLimits`: is `[ RateLimitIP, RateLimitPeerID, RateLimitTopic ]` where each values is an integer with a number of accepted packets per second per IP, Peer ID, and Topic respectively -`bloom, isLightNode, confirmationsEnabled, and rateLimits` are all optional arguments in the handshake. However, if you specify optional field you MUST also specify all optional fields preceding it, in order to be unambiguous. +`bloom, isLightNode, confirmationsEnabled, and rateLimits` are all optional arguments in the handshake. However, if an optional field is specified, all optional fields preceding it MUST also be specified in order to be unambiguous. ## Rate limiting @@ -131,7 +129,7 @@ The protocol requires a key (symmetric or asymmetric) for the following actions: * signing & verifying messages (asymmetric key) * encrypting & decrypting messages (asymmetric or symmetric key). -As asymmetric keys and symmetric keys are required to process incoming messages, +As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory. Keys management for PFS is described in [5/SECURE-TRANSPORT](https://specs.status.im/spec/5). @@ -140,7 +138,7 @@ The Status protocols uses a few particular Whisper topics to achieve its goals. ### Contact code topic -Contact code topic is used to facilitate the discovery of X3DH bundles so that the first message can be PFS-encrypted. +Nodes use the contact code topic to facilitate the discovery of X3DH bundles so that the first message can be PFS-encrypted. Each user publishes periodically to this topic. If user A wants to contact user B, she SHOULD look for their bundle on this contact code topic. @@ -165,9 +163,9 @@ for i = 0; i < topicLen; i++ { Whisper is broadcast-based protocol. In theory, everyone could communicate using a single topic but that would be extremely inefficient. Opposite would be using a unique topic for each conversation, however, this brings privacy concerns because it would be much easier to detect whether and when two parties have an active conversation. -Partitioned topics are used to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. +Nodes use partitioned topics to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. -Currently, the number of partitioned topics is set to `5000`. They MUST be generated following the algorithm below: +Currently, nodes set the number of partitioned topics to `5000`. They MUST be generated following the algorithm below: ```golang var partitionsNum *big.Int = big.NewInt(5000) var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum) @@ -273,20 +271,20 @@ A client SHOULD send to the negotiated topic only if it has received a message f ### Flow -To exchange messages with client B, a client A SHOULD: +To exchange messages with client `B`, a client `A` SHOULD: -- Listen to client's B Contact Code Topic to retrieve their bundle information, including a list of active devices -- Send a message on client's B partitioned topic -- Listen to the Negotiated Topic between A & B -- Once a message is received from B, the Negotiated Topic SHOULD be used +- Listen to client's `B` Contact Code Topic to retrieve their bundle information, including a list of active devices +- Send a message on client's `B` partitioned topic +- Listen to the Negotiated Topic between `A` & `B` +- Once client `A` receives a message from `B`, the Negotiated Topic SHOULD be used ## Message encryption Even though, the protocol specifies an encryption layer that encrypts messages before passing them to the transport layer, Whisper protocol requires each Whisper message to be encrypted anyway. -Public and group messages are encrypted using symmetric encryption and the key is created from a channel name string. The implementation is available in [`shh_generateSymKeyFromPassword`](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_generatesymkeyfrompassword) JSON-RPC method of go-ethereum Whisper implementation. +The node encrypts public and group messages using symmetric encryption, and creates the key from a channel name string. The implementation is available in [`shh_generateSymKeyFromPassword`](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_generatesymkeyfrompassword) JSON-RPC method of go-ethereum Whisper implementation. -One-to-one messages are encrypted using asymmetric encryption. +The node encrypts one-to-one messages using asymmetric encryption. ## Message confirmations @@ -294,7 +292,7 @@ Sending a message is a complex process where many things can go wrong. Message c A node MAY send a message confirmation for any batch of messages received in a packet Messages Code (`0x01`). -A message confirmation is sent using Batch Acknowledge packet (`0x0b`) or Message Response packet (`0x0c`). +A node sends a message confirmation using Batch Acknowledge packet (`0x0b`) or Message Response packet (`0x0c`). The Batch Acknowledge packet is followed by a keccak256 hash of the envelopes batch data (raw bytes). @@ -309,7 +307,7 @@ The Message Response packet is more complex and is followed by a Versioned Messa The supported codes: `1`: means time sync error which happens when an envelope is too old or created in the future (the root cause is no time sync between nodes). -The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, a corresponding confirmation is broadcast by one or more peers. To limit that, both Batch Acknowledge packet (`0x0b`) and Message Response packet (`0x0c`) are not broadcast to peers of the peers, i.e. they do not follow epidemic spread. +The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, one or more peers broadcast a corresponding confirmation. To limit that, both Batch Acknowledge packet (`0x0b`) and Message Response packet (`0x0c`) are not broadcast to peers of the peers, i.e. they do not follow epidemic spread. In the current Status network setup, only `Mailservers` support message confirmations. A client posting a message to the network and after receiving a confirmation can be sure that the message got processed by the `Mailserver`. If additionally, sending a message is limited to non-`Mailserver` peers, it also guarantees that the message got broadcast through the network and it reached the selected `Mailserver`. diff --git a/docs/stable/4-whisper-mailserver.md b/docs/stable/4-whisper-mailserver.md index 4f3133c..e756af0 100644 --- a/docs/stable/4-whisper-mailserver.md +++ b/docs/stable/4-whisper-mailserver.md @@ -67,7 +67,7 @@ The envelope MUST be encrypted with a symmetric key agreed between the requester Historic messages MUST be sent to a peer as a packet with a P2P Message code (`0x7f`) followed by an array of Whisper envelopes. It is incompatible with the original Whisper spec (EIP-627) because it allows only a single envelope, however, an array of envelopes is much more performant. In order to stay compatible with EIP-627, a peer receiving historic message MUST handle both cases. -In order to receive historic messages from a `Mailserver`, a node MUST trust the selected `Mailserver`, that is allow to receive packets with the P2P Message code. By default, such packets are discarded. +In order to receive historic messages from a `Mailserver`, a node MUST trust the selected `Mailserver`, that is allowed to send packets with the P2P Message code. By default, the node discards such packets. Received envelopes MUST be passed through the Whisper envelope pipelines so that they are picked up by registered filters and passed to subscribers. @@ -87,15 +87,15 @@ If `Cursor` is not empty, it means that not all messages were sent due to the se ### Confidentiality -All Whisper envelopes are encrypted. A `Mailserver` node can not inspect their contents. +The node encrypts all Whisper envelopes. A `Mailserver` node can not inspect their contents. ### Altruistic and centralized operator risk -In order to be useful, a `Mailserver` SHOULD be online most of time. That means -you either have to be a bit tech-savvy to run your own node, or rely on someone -else to run it for you. +In order to be useful, a `Mailserver` SHOULD be online most of the time. That means +users either have to be a bit tech-savvy to run their own node, or rely on someone +else to run it for them. -Currently one of Status's legal entities provides `Mailservers` in an altruistic manner, but this is +Currently, one of Status's legal entities provides `Mailservers` in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research. diff --git a/docs/stable/5-secure-transport.md b/docs/stable/5-secure-transport.md index 0698634..4299183 100644 --- a/docs/stable/5-secure-transport.md +++ b/docs/stable/5-secure-transport.md @@ -14,7 +14,7 @@ title: 5/SECURE-TRANSPORT ## Abstract -This document describes how we provide a secure channel between two peers, and thus provide confidentiality, integrity, authenticity and forward secrecy. It is transport-agnostic and works over asynchronous networks. +This document describes how Status provides a secure channel between two peers, and thus provide confidentiality, integrity, authenticity and forward secrecy. It is transport-agnostic and works over asynchronous networks. It builds on the [X3DH](https://signal.org/docs/specifications/x3dh/) and [Double Ratchet](https://signal.org/docs/specifications/doubleratchet/) specifications, with some adaptations to operate in a decentralized environment. @@ -54,11 +54,11 @@ It builds on the [X3DH](https://signal.org/docs/specifications/x3dh/) and [Doubl ## Introduction -In this document we describe how a secure channel is established, and how various conversational security properties are achieved. +This document describes how nodes establish a secure channel, and how various conversational security properties are achieved. ### Definitions -- **Perfect Forward Secrecy** is a feature of specific key-agreement protocols which provide assurances that your session keys will not be compromised even if the private keys of the participants are compromised. Specifically, past messages cannot be decrypted by a third-party who manages to get a hold of a private key. +- **Perfect Forward Secrecy** is a feature of specific key-agreement protocols which provide assurances that session keys will not be compromised even if the private keys of the participants are compromised. Specifically, past messages cannot be decrypted by a third-party who manages to get a hold of a private key. - **Secret channel** describes a communication channel where Double Ratchet algorithm is in use. @@ -89,7 +89,7 @@ See [Account specification](./2-account.md) If Alice later recovers her account, the Double Ratchet state information will not be available, so she is no longer able to decrypt any messages received from existing contacts. -If an incoming message (on the same Whisper/Waku topic) fails to decrypt, a message is replied with the current bundle, so that the other end is notified of the new device. Subsequent communications will use this new bundle. +If an incoming message (on the same Whisper/Waku topic) fails to decrypt, the node replies a message with the current bundle, so that the node notifies the other end of the new device. Subsequent communications will use this new bundle. ## Messaging @@ -99,7 +99,7 @@ The rest of this document is purely about 1:1 and private group chat. Private gr ### End-to-end encryption -End-to-end encryption (E2EE) takes place between two clients. The main cryptographic protocol is a [Status implementation](https://github.com/status-im/doubleratchet/) of the Double Ratchet protocol, which is in turn derived from the [Off-the-Record protocol](https://otr.cypherpunks.ca/Protocol-v3-4.1.1.html), using a different ratchet. The message payload is subsequently encrypted by the transport protocol - Whisper/Waku (see section [Transport Layer](#transport-layer)) -, using symmetric key encryption. +End-to-end encryption (E2EE) takes place between two clients. The main cryptographic protocol is a [Status implementation](https://github.com/status-im/doubleratchet/) of the Double Ratchet protocol, which is in turn derived from the [Off-the-Record protocol](https://otr.cypherpunks.ca/Protocol-v3-4.1.1.html), using a different ratchet. The transport protocol subsequently encrypt the message payload - Whisper/Waku (see section [Transport Layer](#transport-layer)) -, using symmetric key encryption. Furthermore, Status uses the concept of prekeys (through the use of [X3DH](https://signal.org/docs/specifications/x3dh/)) to allow the protocol to operate in an asynchronous environment. It is not necessary for two parties to be online at the same time to initiate an encrypted conversation. Status uses the following cryptographic primitives: @@ -118,7 +118,7 @@ Status uses the following cryptographic primitives: - Elliptic curve Diffie-Hellman key exchange (Curve25519) - AES-256-CTR with HMAC-SHA-256 and IV derived alongside an encryption key - Key derivation is done using HKDF. + The node achieves key derivation using HKDF. ### Prekeys @@ -139,7 +139,7 @@ TODO: See below on bundle retrieval, this seems like enhancement and parameter f X3DH works by having client apps create and make available a bundle of prekeys (the X3DH bundle) that can later be requested by other interlocutors when they wish to start a conversation with a given user. -In the X3DH specification, a shared server is typically used to store bundles and allow other users to download them upon request. Given Status' goal of decentralization, Status chat clients cannot rely on the same type of infrastructure and must achieve the same result using other means. By growing order of convenience and security, the considered approaches are: +In the X3DH specification, nodes typically use a shared server to store bundles and allow other users to download them upon request. Given Status' goal of decentralization, Status chat clients cannot rely on the same type of infrastructure and must achieve the same result using other means. By growing order of convenience and security, the considered approaches are: - contact codes; - public and one-to-one chats; - QR codes; @@ -149,7 +149,7 @@ In the X3DH specification, a shared server is typically used to store bundles an -Currently only public and one-to-one message exchanges and Whisper/Waku is used to exchange bundles. +Currently, only public and one-to-one message exchanges and Whisper/Waku is used to exchange bundles. Since bundles stored in QR codes or ENS records cannot be updated to delete already used keys, the approach taken is to rotate more frequently the bundle (once every 24 hours), which will be propagated by the app through the channel available. @@ -163,12 +163,12 @@ For more information on account generation and trust establishment, see [2/ACCOU #### Initial key exchange flow (X3DH) -The initial key exchange flow is described in [section 3 of the X3DH protocol](https://signal.org/docs/specifications/x3dh/#sending-the-initial-message), with some additional context: +[Section 3 of the X3DH protocol](https://signal.org/docs/specifications/x3dh/#sending-the-initial-message) describes the initial key exchange flow, with some additional context: - The users' identity keys `IK_A` and `IK_B` correspond to their respective Status chat public keys; - Since it is not possible to guarantee that a prekey will be used only once in a decentralized world, the one-time prekey `OPK_B` is not used in this scenario; -- Bundles are not sent to a centralized server, but instead served in a decentralized way as described in [bundle retrieval](#bundle-retrieval). +- Nodes do not send Bundles to a centralized server, but instead served in a decentralized way as described in [bundle retrieval](#bundle-retrieval). -Bob's prekey bundle is retrieved by Alice, however it is not specific to Alice. It contains: +Alice retrieves Bob's prekey bundle, however it is not specific to Alice. It contains: ([protobuf](https://github.com/status-im/status-go/blob/a904d9325e76f18f54d59efc099b63293d3dcad3/services/shhext/chat/encryption.proto#L12)) @@ -205,7 +205,7 @@ The `signature` is generated by sorting `installation-id` in lexicographical ord #### Double Ratchet -Having established the initial shared secret `SK` through X3DH, we can use it to seed a Double Ratchet exchange between Alice and Bob. +Having established the initial shared secret `SK` through X3DH, it can be used to seed a Double Ratchet exchange between Alice and Bob. Please refer to the [Double Ratchet spec](https://signal.org/docs/specifications/doubleratchet/) for more details. @@ -482,18 +482,18 @@ TODO: this requires more detail ## Session management -A peer is identified by two pieces of data: +A node identifies a peer by two pieces of data: 1) An `installation-id` which is generated upon creating a new account in the `Status` application 2) Their identity Whisper/Waku key ### Initialization -A new session is initialized once a successful X3DH exchange has taken place. Subsequent messages will use the established session until re-keying is necessary. +A node initializes a new session once a successful X3DH exchange has taken place. Subsequent messages will use the established session until re-keying is necessary. ### Concurrent sessions -If two sessions are created concurrently between two peers the one with the symmetric key first in byte order SHOULD be used, this marks that the other has expired. +If a node creates two sessions concurrently between two peers, the one with the symmetric key first in byte order SHOULD be used, this marks that the other has expired. ### Re-keying @@ -501,13 +501,13 @@ On receiving a bundle from a given peer with a higher version, the old bundle SH ### Multi-device support -Multi-device support is quite challenging as we don't have a central place where information on which and how many devices (identified by their respective `installation-id`) belongs to a whisper-identity / waku-identity. +Multi-device support is quite challenging as there is not a central place where information on which and how many devices (identified by their respective `installation-id`) belongs to a whisper-identity / waku-identity. -Furthermore we always need to take account recovery in consideration, where the whole device is wiped clean and all the information about any previous sessions is lost. +Furthermore, account recovery always needs to be taken into consideration, where a user wipes clean the whole device and the nodes loses all the information about any previous sessions. -Taking these considerations into account, the way multi-device information is propagated through the network is through x3dh bundles, which will contain information about paired devices as well as information about the sending device. +Taking these considerations into account, the way the network propagates multi-device information using x3dh bundles, which will contain information about paired devices as well as information about the sending device. -This mean that every time a new device is paired, the bundle needs to be updated and propagated with the new information, and the burden is put on the user to make sure the pairing is successful. +This means that every time a new device is paired, the bundle needs to be updated and propagated with the new information, the user has the responsibility to make sure the pairing is successful. The method is loosely based on https://signal.org/docs/specifications/sesame/ . @@ -516,9 +516,9 @@ The method is loosely based on https://signal.org/docs/specifications/sesame/ . When a user adds a new account in the `Status` application, a new `installation-id` will be generated. The device should be paired as soon as possible if other devices are present. Once paired the contacts will be notified of the new device and it will be included in further communications. -Any time a bundle from your `IK` but different `installation-id` is received, the device will be shown to the user and will have to be manually approved, to a maximum of 3. Once that is done any message sent by one device will also be sent to any other enabled device. +If a bundle received from the `IK` is different to the `installation-id`, the device will be shown to the user and will have to be manually approved, to a maximum of 3. Once that is done any message sent by one device will also be sent to any other enabled device. -Once a new device is enabled, a new bundle will be generated which will include pairing information. +Once a user enables a new device, a new bundle will be generated which will include pairing information. The bundle will be propagated to contacts through the usual channels. @@ -527,8 +527,8 @@ Removal of paired devices is a manual step that needs to be applied on each devi ### Sending messages to a paired group When sending a message, the peer will send a message to other `installation-id` that they have seen. -The number of devices is capped to 3, ordered by last activity. -Messages are sent using pairwise encryption, including their own devices. +The node caps the number of devices to 3, ordered by last activity. +The node sends messages using pairwise encryption, including their own devices. ### Account recovery diff --git a/docs/stable/6-payloads.md b/docs/stable/6-payloads.md index 0849c10..0e5bcd1 100644 --- a/docs/stable/6-payloads.md +++ b/docs/stable/6-payloads.md @@ -14,7 +14,7 @@ title: 6/PAYLOADS ## Abstract -This specifications describes how the payload of each message in Status looks +This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases. The payloads aims to be flexible enough to support messaging but also cases @@ -54,11 +54,11 @@ as various clients created using different technologies. ## Introduction -In this document we describe the payload format and some special considerations. +This document describes the payload format and some special considerations. ## Payload wrapper -All payloads are wrapped in a [protobuf record](https://developers.google.com/protocol-buffers/) +The node wraps all payloads in a [protobuf record](https://developers.google.com/protocol-buffers/) record: ```protobuf @@ -69,12 +69,12 @@ message StatusProtocolMessage { ``` `signature` is the bytes of the signed `SHA3-256` of the payload, signed with the key of the author of the message. -The signature is needed 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. +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. ## Encoding -The payload is encoded using [Protobuf](https://developers.google.com/protocol-buffers) +The node encodes the payload using [Protobuf](https://developers.google.com/protocol-buffers) ## Types of messages @@ -150,12 +150,12 @@ message ChatMessage { #### Content types -Content types are required for a proper interpretation of incoming messages. Not each message is plain text but may carry a different information. +A node requires content types for a proper interpretation of incoming messages. Not each message is plain text but may carry different information. The following content types MUST be supported: * `TEXT_PLAIN` identifies a message which content is a plaintext. -There are also other content types that MAY be implemented by the client: +There are other content types that MAY be implemented by the client: * `STICKER` * `STATUS` * `EMOJI` @@ -175,7 +175,7 @@ message StickerMessage { #### Message types -Message types are required to decide how a particular message is encrypted and what metadata needs to be attached when passing a message to the transport layer. For more on this, see [3/WHISPER-USAGE](3-whisper-usage.md) and [10/WAKU-USAGE](10-waku-usage.md). +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 [3/WHISPER-USAGE](3-whisper-usage.md) and [10/WAKU-USAGE](10-waku-usage.md). @@ -196,28 +196,28 @@ Lamport timestamp format is: `clock = `max({timestamp}, chat_clock + 1)` This will satisfy the Lamport requirement, namely: a -> b then T(a) < T(b) -`timestamp` MUST be Unix time calculated when the message is created in milliseconds. This field SHOULD not be relied upon for message ordering. +`timestamp` MUST be Unix time calculated, when the node creates the message, in milliseconds. This field SHOULD not be relied upon for message ordering. -`clock` SHOULD be calculated using the algorithm of [Lamport timestamps](https://en.wikipedia.org/wiki/Lamport_timestamps). When there are messages available in a chat, `clock`'s value is calculated based on the last received message in a particular chat: `max(timeNowInMs, last-message-clock-value + 1)`. If there are no messages, `clock` is initialized with `timestamp`'s value. +`clock` SHOULD be calculated using the algorithm of [Lamport timestamps](https://en.wikipedia.org/wiki/Lamport_timestamps). When there are messages available in a chat, the node calculates `clock`'s value based on the last received message in a particular chat: `max(timeNowInMs, last-message-clock-value + 1)`. If there are no messages, `clock` is initialized with `timestamp`'s value. Messages with a `clock` greater than `120` seconds over the Whisper/Waku timestamp SHOULD be discarded, in order to avoid malicious users to increase the `clock` of a chat arbitrarily. Messages with a `clock` less than `120` seconds under the Whisper/Waku timestamp might indicate an attempt to insert messages in the chat history which is not distinguishable from a `datasync` layer re-transit event. A client MAY mark this messages with a warning to the user, or discard them. -`clock` value is used for the message ordering. Due to the used algorithm and distributed nature of the system, we achieve casual ordering which might produce counter-intuitive results in some edge cases. For example, when one joins a public chat and sends a message before receiving the exist messages, their message `clock` value might be lower and the message will end up in the past when the historical messages are fetched. +The node uses `clock` 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 `clock` value might be lower and the message will end up in the past when the historical messages are fetched. #### Chats -Chat is a structure that helps organize messages. It's usually desired to display messages only from a single recipient or a group of recipients at a time and chats help to achieve that. +Chat is a structure that helps organize messages. It's usually desired to display messages only from a single recipient, or a group of recipients at a time and chats help to achieve that. -All incoming messages can be matched against a chat. Below you can find a table that describes how to calculate a chat ID for each message type. +All incoming messages can be matched against a chat. The below table describes how to calculate a chat ID for each message type. |Message Type|Chat ID Calculation|Direction|Comment| |------------|-------------------|---------|-------| |PUBLIC_GROUP|chat ID is equal to a public channel name; it should equal `chatId` from the message|Incoming/Outgoing|| |ONE_TO_ONE|let `P` be a public key of the recipient; `hex-encode(P)` is a chat ID; use it as `chatId` value in the message|Outgoing|| -|user-message|let `P` be a public key of message's signature; `hex-encode(P)` is a chat ID; discard `chat-id` from message|Incoming|if there is no matched chat, it might be the first message from public key `P`; you can discard it or create a new chat; Status official clients create a new chat| -|PRIVATE_GROUP|use `chatId` from the message|Incoming/Outgoing|find an existing chat by `chatId`; if none is found, we are not a member of that chat or we haven't joined that chat, the message MUST be discarded | +|user-message|let `P` be a public key of message's signature; `hex-encode(P)` is a chat ID; discard `chat-id` from message|Incoming|if there is no matched chat, it might be the first message from public key `P`; the node MAY discard the message or MAY create a new chat; Status official clients create a new chat| +|PRIVATE_GROUP|use `chatId` from the message|Incoming/Outgoing|find an existing chat by `chatId`; if none is found, the user is not a member of that chat or the user hasn't joined that chat, the message MUST be discarded | ### Contact Update @@ -246,13 +246,13 @@ message ContactUpdate { A client SHOULD send a `ContactUpdate` to all the contacts each time: - The ens_name has changed -- The profile image is edited +- A user edits the profile image A client SHOULD also periodically send a `ContactUpdate` to all the contacts, the interval is up to the client, the Status official client sends these updates every 48 hours. ### SyncInstallationContact -`SyncInstallationContact` messages are used to synchronize in a best-effort the contacts to other devices. +The node uses `SyncInstallationContact` messages to synchronize in a best-effort the contacts to other devices. ```protobuf message SyncInstallationContact { @@ -278,7 +278,7 @@ message SyncInstallationContact { ### SyncInstallationPublicChat -`SyncInstallationPublicChat` message is used to synchronize in a best-effort the public chats to other devices. +The node uses `SyncInstallationPublicChat` message to synchronize in a best-effort the public chats to other devices. ```protobuf message SyncInstallationPublicChat { @@ -296,7 +296,7 @@ message SyncInstallationPublicChat { ### PairInstallation -`PairInstallation` messages are used to propagate information about a device to its paired devices. +The node uses `PairInstallation` messages to propagate information about a device to its paired devices. ```protobuf message PairInstallation { @@ -319,14 +319,14 @@ message PairInstallation { ### MembershipUpdateMessage and MembershipUpdateEvent `MembershipUpdateEvent` is a message used to propagate information about group membership changes in a group chat. -The details are in the [Group chats specs](./../draft/7-group-chat.md) +The details are in the [Group chats specs](./../draft/7-group-chat.md). ## Upgradability There are two ways to upgrade the protocol without breaking compatibility: -- Accretion is always supported -- Deletion of existing fields or messages is not supported and might break compatibility +- A node always supports accretion +- A node does not support deletion of existing fields or messages, which might break compatibility ## Security Considerations diff --git a/docs/stable/8-eips.md b/docs/stable/8-eips.md index 612e4a0..adb0ee9 100644 --- a/docs/stable/8-eips.md +++ b/docs/stable/8-eips.md @@ -14,7 +14,7 @@ title: 8/EIPS ## Abstract -In this specification, we describe how Status relates with EIPs. +This specification describes how Status relates with EIPs. ## Table of Contents - [Abstract](#abstract) @@ -24,7 +24,7 @@ In this specification, we describe how Status relates with EIPs. ## Introduction -Status should follow all standards as possible. Whenever a feature is needed, it should be first checked if there is a standard for that, if not, Status should propose a standard. +Status should follow all standards as possible. Whenever the Status app needs a feature, it should be first checked if there is a standard for that, if not, Status should propose a standard. ### Support table diff --git a/docs/stable/9-ethereum-usage.md b/docs/stable/9-ethereum-usage.md index 5b2bff4..ed3a141 100644 --- a/docs/stable/9-ethereum-usage.md +++ b/docs/stable/9-ethereum-usage.md @@ -14,13 +14,13 @@ title: 9/ETHEREUM-USAGE # Status interactions with the Ethereum blockchain -In this document we document all the interactions that the Status client has +This specification documents all the interactions that the Status client has with the [Ethereum](https://ethereum.org/developers/) blockchain. All the interactions are made through [JSON-RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC). Currently [Infura](https://infura.io/) is used. The client assumes high-availability, otherwise it will not be able to interact with the Ethereum blockchain. -We rely on these nodes to validate the integrity of the transaction and report a +Status nodes rely on these Infura nodes to validate the integrity of the transaction and report a consistent history. Key handling is described [here](./2-account.md) @@ -106,10 +106,10 @@ https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d4 ### Fetching balance -We currently fetch the current and historical [ECR20] (https://eips.ethereum.org/EIPS/eip-20) and ETH balance for the user wallet address. +A Status node fetches the current and historical [ECR20] (https://eips.ethereum.org/EIPS/eip-20) and ETH balance for the user wallet address. Collectibles following the [ECR-721](https://eips.ethereum.org/EIPS/eip-721) are also fetched if enabled. -We support by default the following [tokens](https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs). Custom tokens can be added by specifying the `address`, `symbol` and `decimals`. +A Status node supports by default the following [tokens](https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs). Custom tokens can be added by specifying the `address`, `symbol` and `decimals`. #### BlockByHash @@ -140,7 +140,7 @@ https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d4 `FilterLogs` executes a filter query. Status uses this function to filter out logs, using the hash of the block -and the address that we are interested in, both inbound and outbound. +and the address of interest, both inbound and outbound. ``` func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) @@ -163,7 +163,7 @@ https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d4 #### TransactionByHash `TransactionByHash` returns the transaction with the given hash, used to inspect those -transaction made/received by the user. +transactions made/received by the user. ``` func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) @@ -204,7 +204,7 @@ For the `stateofus.eth` username, one can be registered through these [contracts - [Registering a username](https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L113) - [Releasing a username](https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L131) -- [Updating a username] (https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L174) +- [Updating a username](https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L174) ### Slashing @@ -212,11 +212,11 @@ Usernames MUST be in a specific format, otherwise they MAY be slashed: - They MUST only contain alphanumeric characters - They MUST NOT be in the form `0x[0-9a-f]{5}.*` and have more than 12 characters -- They MUST NOT be in the [reserved list] (https://github.com/status-im/ens-usernames/blob/47c4c6c2058be0d80b7d678e611e166659414a3b/config/ens-usernames/reservedNames.js) +- They MUST NOT be in the [reserved list](https://github.com/status-im/ens-usernames/blob/47c4c6c2058be0d80b7d678e611e166659414a3b/config/ens-usernames/reservedNames.js) - They MUST NOT be too short, this is dynamically set in the contract and can be checked against the [contract](https://github.com/status-im/ens-usernames/blob/master/contracts/registry/UsernameRegistrar.sol#L26) - [Slash a reserved username](https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L237) -- [Slash an invalid username] (https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L261) +- [Slash an invalid username](https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L261) - [Slash a username too similar to an address](https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L215) - [Slash a username that is too short](https://github.com/status-im/ens-usernames/blob/77d9394d21a5b6213902473b7a16d62a41d9cd09/contracts/registry/UsernameRegistrar.sol#L200) diff --git a/wordlist.txt b/wordlist.txt index 7bc7045..57e26b5 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -152,6 +152,7 @@ PoW pre prekey prekeys +prepend prepending privkey protobuf