mirror of https://github.com/status-im/specs.git
Remove personal pronouns (#132)
Resolves #115 * Rewrote 'you' and 'your' personal pronouns Additionally I've made related sentences more concise. NOTE I've ignored usages of you and your in comments and in links and section titles * Rewrote 'we' personal pronouns Again not changing usages in comments * Removed 'passive' and/or ambiguous language * Added README information about language mode * Added prepend to word list * Update README.md Co-authored-by: Dean Eigenmann <7621705+decanus@users.noreply.github.com> * Update docs/draft/3-whisper-usage.md Co-authored-by: Dean Eigenmann <7621705+decanus@users.noreply.github.com> * Update docs/draft/3-whisper-usage.md Co-authored-by: Dean Eigenmann <7621705+decanus@users.noreply.github.com> * Added missing 'a's * Moved style related README info into STYLE-GUIDELINE.md * Added reference to Google Technical Writing * Tweaks to maintain consistency of changes across related specs * Addressed spelling and added link to the Discord server * Update docs/draft/12-sticker-pack.md Co-authored-by: Kim De Mey <kim.demey@gmail.com> * Update docs/draft/13-3rd-party.md Co-authored-by: Kim De Mey <kim.demey@gmail.com> * Update docs/draft/13-3rd-party.md Co-authored-by: Kim De Mey <kim.demey@gmail.com> * Update docs/draft/13-3rd-party.md Co-authored-by: Kim De Mey <kim.demey@gmail.com> * Update docs/stable/11-waku-mailserver.md Co-authored-by: Kim De Mey <kim.demey@gmail.com> * Addressed feedback Co-authored-by: Dean Eigenmann <7621705+decanus@users.noreply.github.com> Co-authored-by: Kim De Mey <kim.demey@gmail.com>
This commit is contained in:
parent
7355f4cff0
commit
b21d87ef8f
23
README.md
23
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
|
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
|
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/).
|
Become familiar with the [specification style guidelines](STYLE-GUIDELINE.md) to understand how you should write or amend specifications.
|
||||||
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
## Spec lifecycle
|
## Spec lifecycle
|
||||||
|
|
||||||
|
|
|
@ -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).
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Examples:</summary>
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
</details>
|
|
@ -22,8 +22,8 @@ title: 12/IPFS gateway for Sticker Pack
|
||||||
|
|
||||||
## Abstract
|
## Abstract
|
||||||
|
|
||||||
In this specification, we describe how Status uses the IPFS gateway to store stickers.
|
This specification describes 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.
|
The specification explores image format, how a user uploads stickers and how an end user can see them inside the Status app.
|
||||||
|
|
||||||
## Definition
|
## Definition
|
||||||
|
|
||||||
|
@ -41,25 +41,25 @@ The minimum sticker image resolution is 512x512, and its background SHOULD be tr
|
||||||
|
|
||||||
### Distribution
|
### Distribution
|
||||||
|
|
||||||
Sticker packs are implemented as [ERC721 token](https://eips.ethereum.org/EIPS/eip-721) and contain a set of stickers. These stickers
|
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
|
||||||
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.
|
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.
|
Stickers can be sent in chat only by accounts that own the sticker pack.
|
||||||
|
|
||||||
### IPFS gateway
|
### 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.
|
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.
|
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.
|
The node requires the use of a gateway 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 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.
|
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
|
### 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.
|
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.
|
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
|
### 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.
|
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"}
|
:stickers [{:hash "e301017012207737b75367b8068e5bdd027d7b71a25138c83e155d1f0c9bc5c48ff158724495"}
|
||||||
{:hash "e301017012201a9cdea03f27cda1aede7315f79579e160c7b2b6a2eb51a66e47a96f47fe5284"}]}}
|
{:hash "e301017012201a9cdea03f27cda1aede7315f79579e160c7b2b6a2eb51a66e47a96f47fe5284"}]}}
|
||||||
```
|
```
|
||||||
All assets fields, are contenthash fields as per [EIP 1577](https://eips.ethereum.org/EIPS/eip-1577).
|
All asset 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.
|
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
|
#### 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
|
#### 1. Get total number of sticker packs
|
||||||
Call `packCount()` on the sticker market contract, will return number of sticker pack registered as `uint256`.
|
Call `packCount()` on the sticker market contract, will return number of sticker pack registered as `uint256`.
|
||||||
|
|
||||||
#### 2. Get sticker pack by id
|
#### 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
|
##### 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).
|
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.
|
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
|
##### 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
|
## Copyright
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ title: 13/3RD-PARTY-USAGE
|
||||||
|
|
||||||
## Abstract
|
## 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
|
- communicate with the Ethereum network
|
||||||
- allow users to see address and transaction details on external website
|
- allow users to see address and transaction details on external website
|
||||||
- get fiat/crypto exchange rates
|
- 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?
|
## 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
|
## 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.
|
Status works on mobile devices and therefore can't rely on local node. So all communication to Ethereum network happens via Infura.
|
||||||
|
|
||||||
##### Concerns
|
##### 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.
|
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.
|
Status regularly fetches crypto prices from CryptoCompare. Using that info Status calculates fiat value for transaction or wallet assets.
|
||||||
|
|
||||||
##### Concerns
|
##### 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.
|
If CryptoCompare fails Status won't be able to show fiat equivalent of crypto in wallet.
|
||||||
|
|
||||||
### Collectibles
|
### Collectibles
|
||||||
|
@ -97,7 +97,7 @@ There is a set of services that used for getting information about collectibles:
|
||||||
|
|
||||||
|
|
||||||
##### Concerns
|
##### 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
|
### Iubenda
|
||||||
|
|
||||||
|
|
|
@ -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
|
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
|
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.
|
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
|
Additionally, since anyone can receive Whisper envelopes, it relies on the
|
||||||
ability to decrypt messages to decide who is the correct recipient. We do
|
ability to decrypt messages to decide who is the correct recipient. Status nodes do not
|
||||||
however not rely on this property, but instead implement another secure
|
rely upon this property, and implement another secure transport layer on top of Whisper.
|
||||||
transport layer on top of Whisper.
|
|
||||||
|
|
||||||
Finally, we use an extension of Whisper to provide the ability to do offline
|
Finally, using an extension of Whisper provides the ability to do offline messaging.
|
||||||
messaging.
|
|
||||||
|
|
||||||
## Reason
|
## 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 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
|
* *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
|
* *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
|
## Whisper packets
|
||||||
|
|
||||||
|
@ -79,7 +77,7 @@ encryption properties to support asynchronous chat.
|
||||||
|
|
||||||
## Whisper node configuration
|
## 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:
|
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`
|
* 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
|
`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
|
`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
|
## Rate limiting
|
||||||
|
|
||||||
|
@ -130,7 +128,7 @@ The protocol requires a key (symmetric or asymmetric) for the following actions:
|
||||||
* signing & verifying messages (asymmetric key)
|
* signing & verifying messages (asymmetric key)
|
||||||
* encrypting & decrypting messages (asymmetric or symmetric 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.
|
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).
|
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
|
||||||
|
|
||||||
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.
|
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.
|
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
|
```golang
|
||||||
var partitionsNum *big.Int = big.NewInt(5000)
|
var partitionsNum *big.Int = big.NewInt(5000)
|
||||||
var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum)
|
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
|
### 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
|
- 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
|
- Send a message on client's `B` partitioned topic
|
||||||
- Listen to the Negotiated Topic between A & B
|
- Listen to the Negotiated Topic between `A` & `B`
|
||||||
- Once a message is received from B, the Negotiated Topic SHOULD be used
|
- Once client `A` receives a message from `B`, the Negotiated Topic SHOULD be used
|
||||||
|
|
||||||
## Message encryption
|
## 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.
|
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
|
## 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 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).
|
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:
|
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).
|
`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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ title: 6/PAYLOADS
|
||||||
|
|
||||||
## Abstract
|
## 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.
|
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
|
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
|
## 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
|
## 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.
|
`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.
|
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.
|
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
|
## 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
|
## Types of messages
|
||||||
|
|
||||||
|
@ -148,12 +148,12 @@ message ChatMessage {
|
||||||
|
|
||||||
#### Content types
|
#### 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:
|
The following content types MUST be supported:
|
||||||
* `TEXT_PLAIN` identifies a message which content is a plaintext.
|
* `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`
|
* `STICKER`
|
||||||
* `STATUS`
|
* `STATUS`
|
||||||
* `EMOJI`
|
* `EMOJI`
|
||||||
|
@ -193,7 +193,7 @@ message ImageMessage {
|
||||||
|
|
||||||
#### Message types
|
#### 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).
|
||||||
|
|
||||||
<!-- TODO: This reference is a bit odd, considering the layer payloads should interact with is Secure Transport, and not Whisper. This requires more detail -->
|
<!-- TODO: This reference is a bit odd, considering the layer payloads should interact with is Secure Transport, and not Whisper. This requires more detail -->
|
||||||
|
|
||||||
|
@ -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)
|
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` 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.
|
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
|
#### 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|
|
|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||
|
|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||
|
|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|
|
|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, we are not a member of that chat or we haven't joined that chat, the message MUST be discarded |
|
|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
|
### Contact Update
|
||||||
|
|
||||||
|
@ -264,13 +264,13 @@ message ContactUpdate {
|
||||||
A client SHOULD send a `ContactUpdate` to all the contacts each time:
|
A client SHOULD send a `ContactUpdate` to all the contacts each time:
|
||||||
|
|
||||||
- The ens_name has changed
|
- 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.
|
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
|
||||||
|
|
||||||
`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
|
```protobuf
|
||||||
message SyncInstallationContact {
|
message SyncInstallationContact {
|
||||||
|
@ -296,7 +296,7 @@ message SyncInstallationContact {
|
||||||
|
|
||||||
### SyncInstallationPublicChat
|
### 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
|
```protobuf
|
||||||
message SyncInstallationPublicChat {
|
message SyncInstallationPublicChat {
|
||||||
|
@ -314,7 +314,7 @@ message SyncInstallationPublicChat {
|
||||||
|
|
||||||
### PairInstallation
|
### 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
|
```protobuf
|
||||||
message PairInstallation {
|
message PairInstallation {
|
||||||
|
@ -337,14 +337,14 @@ message PairInstallation {
|
||||||
### MembershipUpdateMessage and MembershipUpdateEvent
|
### MembershipUpdateMessage and MembershipUpdateEvent
|
||||||
|
|
||||||
`MembershipUpdateEvent` is a message used to propagate information about group membership changes in a group chat.
|
`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
|
## Upgradability
|
||||||
|
|
||||||
There are two ways to upgrade the protocol without breaking compatibility:
|
There are two ways to upgrade the protocol without breaking compatibility:
|
||||||
|
|
||||||
- Accretion is always supported
|
- A node always supports accretion
|
||||||
- Deletion of existing fields or messages is not supported and might break compatibility
|
- A node does not support deletion of existing fields or messages, which might break compatibility
|
||||||
|
|
||||||
## Security Considerations
|
## Security Considerations
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,11 @@ title: 7/GROUP-CHAT
|
||||||
|
|
||||||
## Abstract
|
## 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
|
||||||
|
|
||||||
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:
|
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
|
### 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
|
### 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.
|
The author MUST be extracted from it, if the verification fails the event MUST be discarded.
|
||||||
|
|
||||||
#### CHAT_CREATED
|
#### 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`.
|
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
|
#### 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.
|
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`.
|
If the event is valid the chat name SHOULD be changed to `name`.
|
||||||
|
|
||||||
#### MEMBERS_ADDED
|
#### 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.
|
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.
|
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.
|
`members` is an array of hex encoded public keys.
|
||||||
|
|
||||||
#### MEMBER_JOINED
|
#### 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.
|
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.
|
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
|
#### 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.
|
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.
|
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.
|
`members` is an array of hex encoded public keys.
|
||||||
|
|
||||||
#### MEMBER_REMOVED
|
#### 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:
|
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 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.
|
- 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
|
#### 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.
|
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.
|
If the event is valid a client MUST remove the member from the list of `admins` of the chat.
|
||||||
|
|
|
@ -14,10 +14,10 @@ title: 1/CLIENT
|
||||||
|
|
||||||
## Abstract
|
## 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.
|
communicating with other Status clients.
|
||||||
|
|
||||||
We present a reference implementation of the protocol <sup>1</sup> that is used
|
This specification presents a reference implementation of the protocol <sup>1</sup> that is used
|
||||||
in a command line client <sup>2</sup> and a mobile app <sup>3</sup>.
|
in a command line client <sup>2</sup> and a mobile app <sup>3</sup>.
|
||||||
|
|
||||||
This document consists of two parts. The first outlines the specifications that
|
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.
|
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 |
|
| Layer | Purpose | Technology |
|
||||||
| ----------------- | ------------------------------ | ---------------------------- |
|
| ----------------- | ------------------------------ | ---------------------------- |
|
||||||
|
@ -81,7 +81,7 @@ Other aspects, such as how IPFS is used for stickers, how we interact with the E
|
||||||
|
|
||||||
### Protobuf
|
### 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
|
## 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
|
Protocol, v5](https://github.com/ethereum/devp2p/blob/master/rlpx.md) is used, which
|
||||||
allows for TCP-based communication between nodes.
|
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 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)
|
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.
|
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
|
#### Bootstrapping
|
||||||
|
|
||||||
To connect to other Status nodes you need to connect to a bootstrap node. These
|
Bootstrap nodes allow Status nodes to discover and connect to other Status nodes
|
||||||
nodes allow you to discover other nodes of the network.
|
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.
|
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:
|
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://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443`
|
||||||
- `enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156: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
|
These bootstrap nodes MAY change and are not guaranteed to stay this way forever
|
||||||
and at some point we might be forced to change them.
|
and at some point circumstances might force them to change.
|
||||||
|
|
||||||
#### Discovery
|
#### 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
|
light discovery mechanism based on a combination of [Discovery
|
||||||
v5](https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md) and
|
v5](https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md) and
|
||||||
[Rendezvous Protocol](https://github.com/libp2p/specs/tree/master/rendezvous),
|
[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.
|
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
|
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
|
is that these peers might be gone and without peers discovery mechanism, it won't be possible to find
|
||||||
new ones.
|
new ones.
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ For providing an offline inbox, see the complementary [4/WHISPER-MAILSERVER](htt
|
||||||
### Secure Transport
|
### Secure Transport
|
||||||
|
|
||||||
In order to provide confidentiality, integrity, authentication and forward
|
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.
|
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
|
### 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.
|
[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
|
[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),
|
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.
|
Whisper or Waku which also encrypts it.
|
||||||
|
|
||||||
### Payloads and clients
|
### Payloads and clients
|
||||||
|
|
||||||
On top of secure transport, we have various types of data sync clients and
|
On top of secure transport, various types of data sync clients and
|
||||||
payload formats for things like 1:1 chat, group chat and public chat. These have
|
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.
|
various degrees of standardization. Please refer to [6/PAYLOADS](https://specs.status.im/spec/6) for more details.
|
||||||
|
|
||||||
### BIPs and EIPs Standards support
|
### BIPs and EIPs Standards support
|
||||||
|
@ -243,8 +243,8 @@ See [Appendix A](#appendix-a-security-considerations)
|
||||||
|
|
||||||
#### Why devp2p? Why not use libp2p?
|
#### Why devp2p? Why not use libp2p?
|
||||||
|
|
||||||
At the time the main Status clients were being developed, devp2p was the most
|
At the time Status developed the main Status clients, devp2p was the most
|
||||||
mature. However, it is likely we'll move over to libp2p in the future, as it'll
|
mature. However, in the future libp2p is likely to be used, as it'll
|
||||||
provide us with multiple transports, better protocol negotiation, NAT traversal,
|
provide us with multiple transports, better protocol negotiation, NAT traversal,
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
|
@ -306,10 +306,10 @@ methods of spam protection are currently being researched.
|
||||||
|
|
||||||
#### Why do you not use Discovery v5 for node discovery?
|
#### 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
|
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
|
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
|
For some further investigation, see
|
||||||
[here](https://github.com/status-im/swarms/blob/master/ideas/092-disc-v5-research.md).
|
[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?
|
#### 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
|
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
|
whereby participants can sync. Additionally, MVDS is currently not optimized for
|
||||||
large group contexts, which means bandwidth usage will be a lot higher than
|
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:**
|
**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:**
|
**`Mailserver client` privacy:**
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ Privacy for Whisper or Waku hasn't been studied rigorously for various threat mo
|
||||||
|
|
||||||
**Topic hygiene:**
|
**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
|
### Spam resistance
|
||||||
|
|
||||||
|
|
|
@ -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.
|
This allows anyone to listen on a single channel.
|
||||||
|
|
||||||
Additionally, since anyone can receive Waku envelopes, it relies on the
|
Additionally, since anyone can receive Waku envelopes, it relies on the
|
||||||
ability to decrypt messages to decide who is the correct recipient. We do
|
ability to decrypt messages to decide who is the correct recipient. Status nodes do not
|
||||||
however not rely on this property, but instead implement another secure
|
rely upon this property, and implement another secure transport layer on top of Whisper.
|
||||||
transport layer on top of Waku.
|
|
||||||
|
|
||||||
## Reason
|
## Reason
|
||||||
|
|
||||||
|
@ -56,9 +55,9 @@ encryption properties to support asynchronous chat.
|
||||||
|
|
||||||
* *Waku node*: an Ethereum node with Waku V1 enabled
|
* *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
|
* *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
|
* *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
|
## Waku packets
|
||||||
|
|
||||||
|
@ -75,9 +74,9 @@ encryption properties to support asynchronous chat.
|
||||||
|
|
||||||
## Waku node configuration
|
## 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.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
|
* 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)
|
* 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)
|
* signing & verifying messages (asymmetric key)
|
||||||
* encrypting & decrypting messages (asymmetric or symmetric 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.
|
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).
|
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
|
||||||
|
|
||||||
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.
|
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.
|
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
|
```golang
|
||||||
var partitionsNum *big.Int = big.NewInt(5000)
|
var partitionsNum *big.Int = big.NewInt(5000)
|
||||||
var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum)
|
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
|
### 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
|
- 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
|
- Send a message on client's `B` partitioned topic
|
||||||
- Listen to the Negotiated Topic between A & B
|
- Listen to the Negotiated Topic between `A` & `B`
|
||||||
- Once a message is received from B, the Negotiated Topic SHOULD be used
|
- Once client `A` receives a message from `B`, the Negotiated Topic SHOULD be used
|
||||||
|
|
||||||
## Message encryption
|
## 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.
|
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
|
## 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 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).
|
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:
|
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).
|
`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`.
|
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`.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
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.
|
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
|
### 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
|
### 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
|
users either have to be a bit tech-savvy to run their own node, or rely on someone
|
||||||
else to run it for them.
|
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
|
suboptimal from a decentralization, continuance and risk point of view. Coming
|
||||||
up with a better system for this is ongoing research.
|
up with a better system for this is ongoing research.
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ title: 2/ACCOUNT
|
||||||
|
|
||||||
## Abstract
|
## 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
|
## 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 Whisper/Waku chat identity keypair
|
||||||
1. a set of cryptocurrency wallet keypairs
|
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)
|
- Ethereum address (future verification, currently the same base keypair)
|
||||||
- 3 word mnemonic name
|
- 3 word mnemonic name
|
||||||
- identicon
|
- identicon
|
||||||
|
@ -149,22 +149,22 @@ This can be done in the following ways:
|
||||||
```
|
```
|
||||||
- include BundleContainer
|
- include BundleContainer
|
||||||
- a new bundle SHOULD be created at least every 12 hours
|
- a new bundle SHOULD be created at least every 12 hours
|
||||||
- a bundle is only generated when it is used
|
- 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 channel is encrypted in the same way public chats are encrypted.
|
- 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
|
### 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
|
#### 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
|
#### 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.
|
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)
|
- implementation: [gfycat](https://github.com/status-im/status-react/tree/develop/src/status_im/utils/gfycat)
|
||||||
|
|
||||||
#### ENS name
|
#### 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.
|
||||||
|
|
||||||
<!-- TODO: Elaborate on security implications -->
|
<!-- TODO: Elaborate on security implications -->
|
||||||
|
|
||||||
|
|
|
@ -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
|
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
|
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.
|
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
|
Additionally, since anyone can receive Whisper envelopes, it relies on the
|
||||||
ability to decrypt messages to decide who is the correct recipient. We do
|
ability to decrypt messages to decide who is the correct recipient. Status nodes do not
|
||||||
however not rely on this property, but instead implement another secure
|
rely upon this property, and implement another secure transport layer on top of Whisper.
|
||||||
transport layer on top of Whisper.
|
|
||||||
|
|
||||||
Finally, we use an extension of Whisper to provide the ability to do offline
|
Finally, using an extension of Whisper provides the ability to do offline messaging.
|
||||||
messaging.
|
|
||||||
|
|
||||||
## Reason
|
## 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 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
|
* *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
|
* *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
|
## Whisper packets
|
||||||
|
|
||||||
|
@ -81,9 +79,9 @@ encryption properties to support asynchronous chat.
|
||||||
|
|
||||||
## Whisper node configuration
|
## 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`
|
* proof-of-work requirement not larger than `0.002`
|
||||||
* time-to-live not lower than `10` (in seconds)
|
* 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
|
`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
|
`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
|
## Rate limiting
|
||||||
|
|
||||||
|
@ -131,7 +129,7 @@ The protocol requires a key (symmetric or asymmetric) for the following actions:
|
||||||
* signing & verifying messages (asymmetric key)
|
* signing & verifying messages (asymmetric key)
|
||||||
* encrypting & decrypting messages (asymmetric or symmetric 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.
|
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).
|
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
|
||||||
|
|
||||||
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.
|
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.
|
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
|
```golang
|
||||||
var partitionsNum *big.Int = big.NewInt(5000)
|
var partitionsNum *big.Int = big.NewInt(5000)
|
||||||
var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum)
|
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
|
### 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
|
- 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
|
- Send a message on client's `B` partitioned topic
|
||||||
- Listen to the Negotiated Topic between A & B
|
- Listen to the Negotiated Topic between `A` & `B`
|
||||||
- Once a message is received from B, the Negotiated Topic SHOULD be used
|
- Once client `A` receives a message from `B`, the Negotiated Topic SHOULD be used
|
||||||
|
|
||||||
## Message encryption
|
## 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.
|
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
|
## 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 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).
|
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:
|
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).
|
`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`.
|
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`.
|
||||||
|
|
||||||
|
|
|
@ -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.
|
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.
|
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
|
### 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
|
### Altruistic and centralized operator risk
|
||||||
|
|
||||||
In order to be useful, a `Mailserver` SHOULD be online most of time. That means
|
In order to be useful, a `Mailserver` SHOULD be online most of the time. That means
|
||||||
you either have to be a bit tech-savvy to run your own node, or rely on someone
|
users either have to be a bit tech-savvy to run their own node, or rely on someone
|
||||||
else to run it for you.
|
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
|
suboptimal from a decentralization, continuance and risk point of view. Coming
|
||||||
up with a better system for this is ongoing research.
|
up with a better system for this is ongoing research.
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ title: 5/SECURE-TRANSPORT
|
||||||
|
|
||||||
## Abstract
|
## 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.
|
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
|
## 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
|
### 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.
|
- **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 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
|
## 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
|
||||||
|
|
||||||
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.
|
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:
|
Status uses the following cryptographic primitives:
|
||||||
|
@ -118,7 +118,7 @@ Status uses the following cryptographic primitives:
|
||||||
- Elliptic curve Diffie-Hellman key exchange (Curve25519)
|
- Elliptic curve Diffie-Hellman key exchange (Curve25519)
|
||||||
- AES-256-CTR with HMAC-SHA-256 and IV derived alongside an encryption key
|
- 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
|
### 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.
|
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;
|
- contact codes;
|
||||||
- public and one-to-one chats;
|
- public and one-to-one chats;
|
||||||
- QR codes;
|
- QR codes;
|
||||||
|
@ -149,7 +149,7 @@ In the X3DH specification, a shared server is typically used to store bundles an
|
||||||
|
|
||||||
<!-- TODO: Comment, it isn't clear what we actually _do_. It seems as if this is exploring the problem space. From a protocol point of view, it might make sense to describe the interface, and then have a recommendation section later on that specifies what we do. See e.g. Signal's specs where they specify specifics later on. -->
|
<!-- TODO: Comment, it isn't clear what we actually _do_. It seems as if this is exploring the problem space. From a protocol point of view, it might make sense to describe the interface, and then have a recommendation section later on that specifies what we do. See e.g. Signal's specs where they specify specifics later on. -->
|
||||||
|
|
||||||
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.
|
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)
|
#### 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;
|
- 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;
|
- 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))
|
([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
|
#### 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.
|
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
|
## 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
|
1) An `installation-id` which is generated upon creating a new account in the `Status` application
|
||||||
2) Their identity Whisper/Waku key
|
2) Their identity Whisper/Waku key
|
||||||
|
|
||||||
### Initialization
|
### 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
|
### 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
|
### 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
|
||||||
|
|
||||||
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/ .
|
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.
|
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.
|
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
|
### Sending messages to a paired group
|
||||||
|
|
||||||
When sending a message, the peer will send a message to other `installation-id` that they have seen.
|
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.
|
The node caps the number of devices to 3, ordered by last activity.
|
||||||
Messages are sent using pairwise encryption, including their own devices.
|
The node sends messages using pairwise encryption, including their own devices.
|
||||||
|
|
||||||
### Account recovery
|
### Account recovery
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ title: 6/PAYLOADS
|
||||||
|
|
||||||
## Abstract
|
## 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.
|
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
|
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
|
## 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
|
## 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:
|
record:
|
||||||
|
|
||||||
```protobuf
|
```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.
|
`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.
|
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.
|
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
|
## 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
|
## Types of messages
|
||||||
|
|
||||||
|
@ -150,12 +150,12 @@ message ChatMessage {
|
||||||
|
|
||||||
#### Content types
|
#### 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:
|
The following content types MUST be supported:
|
||||||
* `TEXT_PLAIN` identifies a message which content is a plaintext.
|
* `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`
|
* `STICKER`
|
||||||
* `STATUS`
|
* `STATUS`
|
||||||
* `EMOJI`
|
* `EMOJI`
|
||||||
|
@ -175,7 +175,7 @@ message StickerMessage {
|
||||||
|
|
||||||
#### Message types
|
#### 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).
|
||||||
|
|
||||||
<!-- TODO: This reference is a bit odd, considering the layer payloads should interact with is Secure Transport, and not Whisper/Waku. This requires more detail -->
|
<!-- TODO: This reference is a bit odd, considering the layer payloads should interact with is Secure Transport, and not Whisper/Waku. This requires more detail -->
|
||||||
|
|
||||||
|
@ -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)
|
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` 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.
|
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
|
#### 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|
|
|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||
|
|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||
|
|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|
|
|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, we are not a member of that chat or we haven't joined that chat, the message MUST be discarded |
|
|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
|
### Contact Update
|
||||||
|
|
||||||
|
@ -246,13 +246,13 @@ message ContactUpdate {
|
||||||
A client SHOULD send a `ContactUpdate` to all the contacts each time:
|
A client SHOULD send a `ContactUpdate` to all the contacts each time:
|
||||||
|
|
||||||
- The ens_name has changed
|
- 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.
|
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
|
||||||
|
|
||||||
`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
|
```protobuf
|
||||||
message SyncInstallationContact {
|
message SyncInstallationContact {
|
||||||
|
@ -278,7 +278,7 @@ message SyncInstallationContact {
|
||||||
|
|
||||||
### SyncInstallationPublicChat
|
### 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
|
```protobuf
|
||||||
message SyncInstallationPublicChat {
|
message SyncInstallationPublicChat {
|
||||||
|
@ -296,7 +296,7 @@ message SyncInstallationPublicChat {
|
||||||
|
|
||||||
### PairInstallation
|
### 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
|
```protobuf
|
||||||
message PairInstallation {
|
message PairInstallation {
|
||||||
|
@ -319,14 +319,14 @@ message PairInstallation {
|
||||||
### MembershipUpdateMessage and MembershipUpdateEvent
|
### MembershipUpdateMessage and MembershipUpdateEvent
|
||||||
|
|
||||||
`MembershipUpdateEvent` is a message used to propagate information about group membership changes in a group chat.
|
`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
|
## Upgradability
|
||||||
|
|
||||||
There are two ways to upgrade the protocol without breaking compatibility:
|
There are two ways to upgrade the protocol without breaking compatibility:
|
||||||
|
|
||||||
- Accretion is always supported
|
- A node always supports accretion
|
||||||
- Deletion of existing fields or messages is not supported and might break compatibility
|
- A node does not support deletion of existing fields or messages, which might break compatibility
|
||||||
|
|
||||||
## Security Considerations
|
## Security Considerations
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ title: 8/EIPS
|
||||||
|
|
||||||
## Abstract
|
## Abstract
|
||||||
|
|
||||||
In this specification, we describe how Status relates with EIPs.
|
This specification describes how Status relates with EIPs.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
- [Abstract](#abstract)
|
- [Abstract](#abstract)
|
||||||
|
@ -24,7 +24,7 @@ In this specification, we describe how Status relates with EIPs.
|
||||||
|
|
||||||
## Introduction
|
## 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
|
### Support table
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ title: 9/ETHEREUM-USAGE
|
||||||
|
|
||||||
# Status interactions with the Ethereum blockchain
|
# 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.
|
with the [Ethereum](https://ethereum.org/developers/) blockchain.
|
||||||
|
|
||||||
All the interactions are made through [JSON-RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC).
|
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
|
Currently [Infura](https://infura.io/) is used. The client assumes high-availability, otherwise
|
||||||
it will not be able to interact with the Ethereum blockchain.
|
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.
|
consistent history.
|
||||||
|
|
||||||
Key handling is described [here](./2-account.md)
|
Key handling is described [here](./2-account.md)
|
||||||
|
@ -106,10 +106,10 @@ https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d4
|
||||||
|
|
||||||
### Fetching balance
|
### 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.
|
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
|
#### BlockByHash
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d4
|
||||||
`FilterLogs` executes a filter query.
|
`FilterLogs` executes a filter query.
|
||||||
|
|
||||||
Status uses this function to filter out logs, using the hash of the block
|
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)
|
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
|
||||||
|
|
||||||
`TransactionByHash` returns the transaction with the given hash, used to inspect those
|
`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)
|
func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error)
|
||||||
|
|
|
@ -152,6 +152,7 @@ PoW
|
||||||
pre
|
pre
|
||||||
prekey
|
prekey
|
||||||
prekeys
|
prekeys
|
||||||
|
prepend
|
||||||
prepending
|
prepending
|
||||||
privkey
|
privkey
|
||||||
protobuf
|
protobuf
|
||||||
|
|
Loading…
Reference in New Issue