diff --git a/assets/js/search-data.json b/assets/js/search-data.json index 39fede9..b495284 100644 --- a/assets/js/search-data.json +++ b/assets/js/search-data.json @@ -2,194 +2,194 @@ "doc": "1/CLIENT", "title": "1/CLIENT", "content": "Version: 0.3 . Status: Stable . Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Dean Eigenmann dean@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order) . ", - "url": "https://specs.status.im/stable/1", - "relUrl": "/stable/1" + "url": "https://specs.status.im/spec/1", + "relUrl": "/spec/1" },"1": { "doc": "1/CLIENT", "title": "Abstract", "content": "This specification describes how to write a Status client for communicating with other Status clients. This specification presents a reference implementation of the protocol 1 that is used in a command line client 2 and a mobile app 3. This document consists of two parts. The first outlines the specifications that have to be implemented in order to be a full Status client. The second gives a design rationale and answers some common questions. ", - "url": "https://specs.status.im/stable/1#abstract", - "relUrl": "/stable/1#abstract" + "url": "https://specs.status.im/spec/1#abstract", + "relUrl": "/spec/1#abstract" },"2": { "doc": "1/CLIENT", "title": "Table of Contents", "content": ". | Abstract | Table of Contents | Introduction . | Protocol layers | Protobuf | . | Components . | P2P Overlay . | Node discovery and roles | Bootstrapping | Discovery | Mobile nodes | . | Transport privacy and Whisper/Waku usage | Secure Transport | Data Sync | Payloads and clients | BIPs and EIPs Standards support | . | Security Considerations | Design Rationale . | P2P Overlay . | Why devp2p? Why not use libp2p? | What about other RLPx subprotocols like LES, and Swarm? | Why do you use Whisper? | Why do you use Waku? | Why is PoW for Waku set so low? | Why do you not use Discovery v5 for node discovery? | I heard something about Mailservers being trusted somehow? | . | Data sync . | Why is MVDS not used for public chats? | . | . | Footnotes | Appendix A: Security considerations . | Scalability and UX | Privacy | Spam resistance | Censorship resistance | . | Acknowledgments | Changelog . | Version 0.3 | . | . ", - "url": "https://specs.status.im/stable/1#table-of-contents", - "relUrl": "/stable/1#table-of-contents" + "url": "https://specs.status.im/spec/1#table-of-contents", + "relUrl": "/spec/1#table-of-contents" },"3": { "doc": "1/CLIENT", "title": "Introduction", "content": "Protocol layers . 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 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 | . | Data and payloads | End user functionality | 1:1, group chat, public chat | . | Data sync | Data consistency | MVDS. | . | Secure transport | Confidentiality, PFS, etc | Double Ratchet | . | Transport privacy | Routing, Metadata protection | Waku / Whisper | . | P2P Overlay | Overlay routing, NAT traversal | devp2p | . Protobuf . protobuf is used in different layers, version proto3 used is unless stated otherwise. ", - "url": "https://specs.status.im/stable/1#introduction", - "relUrl": "/stable/1#introduction" + "url": "https://specs.status.im/spec/1#introduction", + "relUrl": "/spec/1#introduction" },"4": { "doc": "1/CLIENT", "title": "Components", "content": "P2P Overlay . Status clients run on a public, permissionless peer-to-peer network, as specified by the devP2P network protocols. devP2P provides a protocol for node discovery which is in draft mode here. See more on node discovery and management in the next section. To communicate between Status nodes, the RLPx Transport Protocol, v5 is used, which allows for TCP-based communication between nodes. On top of this RLPx-based subprotocols are ran, the client SHOULD NOT use Whisper V6, the client SHOULD use Waku V1 for privacy-preserving messaging and efficient usage of a node’s bandwidth. Node discovery and roles . There are four types of node roles: . | Bootstrap node | Whisper/Waku relayer | Mailserver (servers and clients) | Mobile node (Status Clients) | . A standard Status client MUST implement both Whisper/Waku relayer and Mobile node node types. The other node types are optional, but it is RECOMMEND to implement a Mailserver client mode, otherwise the user experience is likely to be poor. Bootstrapping . Bootstrap nodes allow Status nodes to discover and connect to other Status nodes in the network. Currently, Status Gmbh provides the main bootstrap nodes, but anyone can run these provided they are connected to the rest of the Whisper/Waku network. Status maintains a list of production fleet bootstrap nodes in the following locations: . Hong Kong: . | enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443 | enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443 | . Amsterdam: . | enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443 | enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443 | . Central US: . | enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443 | enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443 | . These bootstrap nodes MAY change and are not guaranteed to stay this way forever and at some point circumstances might force them to change. Discovery . A Status client MUST discover or have a list of peers to connect to. Status uses a light discovery mechanism based on a combination of Discovery v5 and Rendezvous Protocol, (with some modifications). Additionally, some static nodes MAY also be used. A Status client MUST use at least one discovery method or use static nodes to communicate with other clients. Discovery V5 uses bootstrap nodes to discover other peers. Bootstrap nodes MUST support Discovery V5 protocol as well in order to provide peers. It is kademlia-based discovery mechanism and it might consume significant (at least on mobile) amount of network traffic to operate. In order to take advantage from simpler and more mobile-friendly peers discovery mechanism, i.e. Rendezvous protocol, one MUST provide a list of Rendezvous nodes which speak Rendezvous protocol. Rendezvous protocol is request-response discovery mechanism. It uses Ethereum Node Records (ENR) to report discovered peers. Both peers discovery mechanisms use topics to provide peers with certain capabilities. There is no point in returning peers that do not support a particular protocol. Status nodes that want to be discovered MUST register to Discovery V5 and/or Rendezvous with the whisper topic. Status nodes that are Mailservers and want to be discoverable MUST additionally register with the whispermail topic. It is RECOMMENDED to use both mechanisms but at the same time implement a structure called PeerPool. PeerPool is responsible for maintaining an optimal number of peers. For mobile nodes, there is no significant advantage to have more than 2-3 peers and one Mailserver. PeerPool can notify peers discovery protocol implementations that they should suspend their execution because the optimal number of peers is found. They should resume if the number of connected peers drops or a Mailserver disconnects. It is worth noticing that an efficient caching strategy MAY be of great use, especially, on mobile devices. Discovered peers can be cached as they rarely change and used when the client starts again. In such a case, there might be no need to even start peers discovery protocols because cached peers will satisfy the optimal number of peers. Alternatively, a client MAY rely exclusively on a list of static peers. This is the most efficient way because there are no peers discovery algorithm overhead introduced. The disadvantage is that these peers might be gone and without peers discovery mechanism, it won’t be possible to find new ones. The current list of static peers is published on https://fleets.status.im/. eth.prod is the current group of peers the official Status client uses. The others are test networks. Finally, Waku node addresses can be retrieved by traversing the merkle tree found at fleets.status.im, as described in EIP-1459. Mobile nodes . A Mobile node is a Whisper and/or Waku node which connects to part of the respective Whisper and/or Waku network(s). A Mobile node MAY relay messages. See next section for more details on how to use Whisper and/or Waku to communicate with other Status nodes. Transport privacy and Whisper / Waku usage . Once a Whisper and/or Waku node is up and running there are some specific settings required to communicate with other Status nodes. See 3/WHISPER-USAGE and 10/WAKU-USAGE for more details. For providing an offline inbox, see the complementary 4/WHISPER-MAILSERVER and 11/WAKU-MAILSERVER. Secure Transport . In order to provide confidentiality, integrity, authentication and forward 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 for more. Data Sync . MVDS is used for 1:1 and group chats, however it is currently not in use for public chats. Status payloads are serialized and then wrapped inside an MVDS message which is added to an MVDS payload, the node encrypts this payload (if necessary for 1-to-1 / group-chats) and sends it using Whisper or Waku which also encrypts it. Payloads and clients . On top of secure transport, various types of data sync clients and the node uses payload formats for things like 1:1 chat, group chat and public chat. These have various degrees of standardization. Please refer to 6/PAYLOADS for more details. BIPs and EIPs Standards support . For a list of EIPs and BIPs that SHOULD be supported by Status client, please see 8/EIPS. ", - "url": "https://specs.status.im/stable/1#components", - "relUrl": "/stable/1#components" + "url": "https://specs.status.im/spec/1#components", + "relUrl": "/spec/1#components" },"5": { "doc": "1/CLIENT", "title": "Security Considerations", "content": "See Appendix A . ", - "url": "https://specs.status.im/stable/1#security-considerations", - "relUrl": "/stable/1#security-considerations" + "url": "https://specs.status.im/spec/1#security-considerations", + "relUrl": "/spec/1#security-considerations" },"6": { "doc": "1/CLIENT", "title": "Design Rationale", "content": "P2P Overlay . Why devp2p? Why not use libp2p? . At the time Status developed the main Status clients, devp2p was the most mature. However, in the future libp2p is likely to be used, as it’ll provide us with multiple transports, better protocol negotiation, NAT traversal, etc. For very experimental bridge support, see the bridge between libp2p and devp2p in Murmur. What about other RLPx subprotocols like LES, and Swarm? . Status is primarily optimized for resource restricted devices, and at present time light client support for these protocols are suboptimal. This is a work in progress. For better Ethereum light client support, see Re-enable LES as option. For better Swarm support, see Swarm adaptive nodes. For transaction support, Status clients currently have to rely on Infura. Status clients currently do not offer native support for file storage. Why do you use Whisper? . Whisper is one of the three parts of the vision of Ethereum as the world computer, Ethereum and Swarm being the other two. Status was started as an encapsulation of and a clear window to this world computer. Why do you use Waku? . Waku is a direct upgrade and replacement for Whisper, the main motivation for developing and implementing Waku can be found in the Waku specs. Waku was created to incrementally improve in areas that Whisper is lacking in, with special attention to resource restricted devices. We specify the standard for Waku messages in order to ensure forward compatibility of different Waku clients, backwards compatibility with Whisper clients, as well as to allow multiple implementations of Waku and its capabilities. We also modify the language to be more unambiguous, concise and consistent. Considerable work has gone into the active development of Ethereum, in contrast Whisper is not currently under active development, and it has several drawbacks. Among others: . | Whisper is very wasteful bandwidth-wise and doesn’t appear to be scalable | Proof of work is a poor spam protection mechanism for heterogeneous devices | The privacy guarantees provided are not rigorous | There are no incentives to run a node | . Finding a more suitable transport privacy is an ongoing research effort, together with Vac and other teams in the space. Why is PoW for Waku set so low? . A higher PoW would be desirable, but this kills the battery on mobile phones, which is a prime target for Status clients. This means the network is currently vulnerable to DDoS attacks. Alternative methods of spam protection are currently being researched. Why do you not use Discovery v5 for node discovery? . At the time of implementing dynamic node discovery, Discovery v5 wasn’t completed yet. Additionally, running a DHT on a mobile leads to slow node discovery, bad battery and poor bandwidth usage. Instead, each client can choose to turn on Discovery v5 for a short period until the node populates their peer list. For some further investigation, see here. I heard something about Mailservers being trusted somehow? . In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it knows the bloom filter of the topics the node is interested in, when it is online as well as many metadata like IP address. Data sync . Why is MVDS not used for public chats? . Currently, public chats are broadcast-based, and there’s no direct way of finding out who is receiving messages. Hence there’s no clear group sync state context whereby participants can sync. Additionally, MVDS is currently not optimized for large group contexts, which means bandwidth usage will be a lot higher than reasonable. See P2P Data Sync for Mobile for more. This is an active area of research. ", - "url": "https://specs.status.im/stable/1#design-rationale", - "relUrl": "/stable/1#design-rationale" + "url": "https://specs.status.im/spec/1#design-rationale", + "relUrl": "/spec/1#design-rationale" },"7": { "doc": "1/CLIENT", "title": "Footnotes", "content": ". | https://github.com/status-im/status-protocol-go/ | https://github.com/status-im/status-console-client/ | https://github.com/status-im/status-react/ | . ", - "url": "https://specs.status.im/stable/1#footnotes", - "relUrl": "/stable/1#footnotes" + "url": "https://specs.status.im/spec/1#footnotes", + "relUrl": "/spec/1#footnotes" },"8": { "doc": "1/CLIENT", "title": "Appendix A: Security considerations", "content": "There are several security considerations to take into account when running Status. Chief among them are: scalability, DDoS-resistance and privacy. These also vary depending on what capabilities are used, such as Mailserver, light node, and so on. Scalability and UX . Bandwidth usage: . In version 1 of Status, bandwidth usage is likely to be an issue. In Status version 1.1 this is partially addressed with Waku usage, see the theoretical scaling model. Mailserver High Availability requirement: . A Mailserver has to be online to receive messages for other nodes, this puts a high availability requirement on it. Gossip-based routing: . Use of gossip-based routing doesn’t necessarily scale. It means each node can see a message multiple times, and having too many light nodes can cause propagation probability that is too low. See Whisper vs PSS for more and a possible Kademlia based alternative. Lack of incentives: . Status currently lacks incentives to run nodes, which means node operators are more likely to create centralized choke points. Privacy . Light node privacy: . The main privacy concern with light nodes is that directly connected peers will know that a message originates from them (as it are the only ones it sends). This means nodes can make assumptions about what messages (topics) their peers are interested in. Bloom filter privacy: . 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 trilemma. Mailserver client privacy: . A Mailserver client has to trust a Mailserver, which means they can send direct traffic. This reveals what topics / bloom filter a node is interested in, along with its peerID (with IP). Privacy guarantees not rigorous: . Privacy for Whisper or Waku hasn’t been studied rigorously for various threat models like global passive adversary, local active attacker, etc. This is unlike e.g. Tor and mixnets. Topic hygiene: . Similar to bloom filter privacy, using a very specific topic reveals more information. See scalability model linked above. Spam resistance . PoW bad for heterogeneous devices: . Proof of work is a poor spam prevention mechanism. A mobile device can only have a very low PoW in order not to use too much CPU / burn up its phone battery. This means someone can spin up a powerful node and overwhelm the network. Mailserver trusted connection: . A Mailserver has a direct TCP connection, which means they are trusted to send traffic. This means a malicious or malfunctioning Mailserver can overwhelm an individual node. Censorship resistance . Devp2p TCP port blockable: . By default Devp2p runs on port 30303, which is not commonly used for any other service. This means it is easy to censor, e.g. airport WiFi. This can be mitigated somewhat by running on e.g. port 80 or 443, but there are still outstanding issues. See libp2p and Tor’s Pluggable Transport for how this can be improved. See https://github.com/status-im/status-react/issues/6351 for some discussion. ", - "url": "https://specs.status.im/stable/1#appendix-a-security-considerations", - "relUrl": "/stable/1#appendix-a-security-considerations" + "url": "https://specs.status.im/spec/1#appendix-a-security-considerations", + "relUrl": "/spec/1#appendix-a-security-considerations" },"9": { "doc": "1/CLIENT", "title": "Acknowledgments", "content": "Jacek Sieka . ", - "url": "https://specs.status.im/stable/1#acknowledgments", - "relUrl": "/stable/1#acknowledgments" + "url": "https://specs.status.im/spec/1#acknowledgments", + "relUrl": "/spec/1#acknowledgments" },"10": { "doc": "1/CLIENT", "title": "Changelog", "content": "Version 0.3 . Released May 22, 2020 . | Added that Waku SHOULD be used | Added that Whisper SHOULD NOT be used | Added language to include Waku in all relevant places | Change to keep Mailserver term consistent | . ", - "url": "https://specs.status.im/stable/1#changelog", - "relUrl": "/stable/1#changelog" + "url": "https://specs.status.im/spec/1#changelog", + "relUrl": "/spec/1#changelog" },"11": { "doc": "1/CLIENT", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/1#copyright", - "relUrl": "/stable/1#copyright" + "url": "https://specs.status.im/spec/1#copyright", + "relUrl": "/spec/1#copyright" },"12": { "doc": "10/WAKU-USAGE", "title": "10/WAKU-USAGE", "content": "Version: 0.1 . Status: Stable . Authors: Adam Babik adam@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order) . | Status Waku Usage Specification . | Abstract | Reason | Terminology | Waku packets | Waku node configuration | Status | Rate limiting | Keys management . | Contact code topic | Partitioned topic | Public chats | Group chat topic | Negotiated topic | . | Message encryption | Message confirmations | Waku V1 extensions . | Request historic messages . | wakuext_requestMessages | . | . | Changelog . | Version 0.1 | . | . | . ", - "url": "https://specs.status.im/stable/10", - "relUrl": "/stable/10" + "url": "https://specs.status.im/spec/10", + "relUrl": "/spec/10" },"13": { "doc": "10/WAKU-USAGE", "title": "Abstract", "content": "Status uses Waku to provide privacy-preserving routing and messaging on top of devP2P. Waku uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Waku topic. This allows anyone to listen on a single channel. Additionally, since anyone can receive Waku envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper. ", - "url": "https://specs.status.im/stable/10#abstract", - "relUrl": "/stable/10#abstract" + "url": "https://specs.status.im/spec/10#abstract", + "relUrl": "/spec/10#abstract" },"14": { "doc": "10/WAKU-USAGE", "title": "Reason", "content": "Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat. ", - "url": "https://specs.status.im/stable/10#reason", - "relUrl": "/stable/10#reason" + "url": "https://specs.status.im/spec/10#reason", + "relUrl": "/spec/10#reason" },"15": { "doc": "10/WAKU-USAGE", "title": "Terminology", "content": ". | Waku node: an Ethereum node with Waku V1 enabled | Waku network: a group of Waku nodes connected together through the internet connection and forming a graph | Message: a decrypted Waku message | Offline message: an archived envelope | Envelope: an encrypted message with metadata like topic and Time-To-Live | . ", - "url": "https://specs.status.im/stable/10#terminology", - "relUrl": "/stable/10#terminology" + "url": "https://specs.status.im/spec/10#terminology", + "relUrl": "/spec/10#terminology" },"16": { "doc": "10/WAKU-USAGE", "title": "Waku packets", "content": "| Packet Name | Code | References | . | Status | 0 | Status, WAKU-1 | . | Messages | 1 | WAKU-1 | . | Batch Ack | 11 | Undocumented. Marked for Deprecation | . | Message Response | 12 | WAKU-1 | . | Status Update | 22 | WAKU-1 | . | P2P Request Complete | 125 | 4/WAKU-MAILSERVER | . | P2P Request | 126 | 4/WAKU-MAILSERVER, WAKU-1 | . | P2P Messages | 127 | 4/WAKU-MAILSERVER, WAKU-1 | . ", - "url": "https://specs.status.im/stable/10#waku-packets", - "relUrl": "/stable/10#waku-packets" + "url": "https://specs.status.im/spec/10#waku-packets", + "relUrl": "/spec/10#waku-packets" },"17": { "doc": "10/WAKU-USAGE", "title": "Waku node configuration", "content": "A Waku node must be properly configured to receive messages from Status clients. Nodes use Waku’s Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: . | proof-of-work requirement not larger than 0.002 for payloads less than 50,000 bytes | proof-of-work requirement not larger than 0.000002 for payloads greater than or equal to 50,000 bytes | time-to-live not lower than 10 (in seconds) | . ", - "url": "https://specs.status.im/stable/10#waku-node-configuration", - "relUrl": "/stable/10#waku-node-configuration" + "url": "https://specs.status.im/spec/10#waku-node-configuration", + "relUrl": "/spec/10#waku-node-configuration" },"18": { "doc": "10/WAKU-USAGE", "title": "Status", "content": "Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items: . [ [ pow-requirement-key pow-requirement ] [ bloom-filter-key bloom-filter ] [ light-node-key light-node ] [ confirmations-enabled-key confirmations-enabled ] [ rate-limits-key rate-limits ] [ topic-interest-key topic-interest ] ] . | Option Name | Key | Type | Description | References | . | pow-requirement | 0x00 | uint64 | minimum PoW accepted by the peer | WAKU-1#pow-requirement | . | bloom-filter | 0x01 | []byte | bloom filter of Waku topic accepted by the peer | WAKU-1#bloom-filter | . | light-node | 0x02 | bool | when true, the peer won’t forward envelopes through the Messages packet. | WAKU-1#light-node | . | confirmations-enabled | 0x03 | bool | when true, the peer will send message confirmations | WAKU-1#confirmations-enabled-field | . | rate-limits | 0x04 |   | See Rate limiting | WAKU-1#rate-limits | . | topic-interest | 0x05 | [10000][4]byte | Topic interest is used to share a node’s interest in envelopes with specific topics. It does this in a more bandwidth considerate way, at the expense of some metadata protection. Peers MUST only send envelopes with specified topics. | WAKU-1#topic-interest, the theoretical scaling model | . ", - "url": "https://specs.status.im/stable/10#status", - "relUrl": "/stable/10#status" + "url": "https://specs.status.im/spec/10#status", + "relUrl": "/spec/10#status" },"19": { "doc": "10/WAKU-USAGE", "title": "Rate limiting", "content": "In order to provide an optional very basic Denial-of-Service attack protection, each node SHOULD define its own rate limits. The rate limits SHOULD be applied on IPs, peer IDs, and envelope topics. Each node MAY decide to whitelist, i.e. do not rate limit, selected IPs or peer IDs. If a peer exceeds node’s rate limits, the connection between them MAY be dropped. Each node SHOULD broadcast its rate limits to its peers using rate limits in status-options via packet code 0x00 or 0x22. The rate limits is RLP-encoded information: . [ IP limits, PeerID limits, Topic limits ] . IP limits: 4-byte wide unsigned integer PeerID limits: 4-byte wide unsigned integer Topic limits: 4-byte wide unsigned integer . The rate limits MAY also be sent as an optional parameter in the handshake. Each node SHOULD respect rate limits advertised by its peers. The number of packets SHOULD be throttled in order not to exceed peer’s rate limits. If the limit gets exceeded, the connection MAY be dropped by the peer. ", - "url": "https://specs.status.im/stable/10#rate-limiting", - "relUrl": "/stable/10#rate-limiting" + "url": "https://specs.status.im/spec/10#rate-limiting", + "relUrl": "/spec/10#rate-limiting" },"20": { "doc": "10/WAKU-USAGE", "title": "Keys management", "content": "The protocol requires a key (symmetric or asymmetric) for the following actions: . | signing & verifying messages (asymmetric key) | encrypting & decrypting messages (asymmetric or symmetric key). | . As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory. Keys management for PFS is described in 5/SECURE-TRANSPORT. The Status protocols uses a few particular Waku topics to achieve its goals. Contact code topic . 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. Contact code topic MUST be created following the algorithm below: . contactCode := \"0x\" + hexEncode(activePublicKey) + \"-contact-code\" var hash []byte = keccak256(contactCode) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Partitioned topic . 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. Nodes use partitioned topics to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. Currently, nodes set the number of partitioned topics to 5000. They MUST be generated following the algorithm below: . var partitionsNum *big.Int = big.NewInt(5000) var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum) partitionTopic := \"contact-discovery-\" + strconv.FormatInt(partition.Int64(), 10) var hash []byte = keccak256(partitionTopic) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Public chats . A public chat MUST use a topic derived from a public chat name following the algorithm below: . var hash []byte hash = keccak256(name) topicLen = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Group chat topic . Group chats does not have a dedicated topic. All group chat messages (including membership updates) are sent as one-to-one messages to multiple recipients. Negotiated topic . When a client sends a one to one message to another client, it MUST listen to their negotiated topic. This is computed by generating a diffie-hellman key exchange between two members and taking the first four bytes of the SHA3-256 of the key generated. sharedKey, err := ecies.ImportECDSA(myPrivateKey).GenerateShared( ecies.ImportECDSAPublic(theirPublicKey), 16, 16, ) hexEncodedKey := hex.EncodeToString(sharedKey) var hash []byte = keccak256(hexEncodedKey) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . A client SHOULD send to the negotiated topic only if it has received a message from all the devices included in the conversation. Flow . To exchange messages with client B, a client A SHOULD: . | Listen to client’s B Contact Code Topic to retrieve their bundle information, including a list of active devices | Send a message on client’s B partitioned topic | Listen to the Negotiated Topic between A & B | Once client A receives a message from B, the Negotiated Topic SHOULD be used | . ", - "url": "https://specs.status.im/stable/10#keys-management", - "relUrl": "/stable/10#keys-management" + "url": "https://specs.status.im/spec/10#keys-management", + "relUrl": "/spec/10#keys-management" },"21": { "doc": "10/WAKU-USAGE", "title": "Message encryption", "content": "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. 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 JSON-RPC method of go-ethereum Whisper implementation. The node encrypts one-to-one messages using asymmetric encryption. ", - "url": "https://specs.status.im/stable/10#message-encryption", - "relUrl": "/stable/10#message-encryption" + "url": "https://specs.status.im/spec/10#message-encryption", + "relUrl": "/spec/10#message-encryption" },"22": { "doc": "10/WAKU-USAGE", "title": "Message confirmations", "content": "Sending a message is a complex process where many things can go wrong. Message confirmations tell a node that a message originating from it has been seen by its direct peers. A node MAY send a message confirmation for any batch of messages received in a packet Messages Code (0x01). 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 Message Response packet is more complex and is followed by a Versioned Message Response: . [ Version, Response] . Version: a version of the Message Response, equal to 1, Response: [ Hash, Errors ] where Hash is a keccak256 hash of the envelopes batch data (raw bytes) for which the confirmation is sent and Errors is a list of envelope errors when processing the batch. A single error contains [ Hash, Code, Description ] where Hash is a hash of the processed envelope, Code is an error code and Description is a descriptive error message. The supported codes: 1: means time sync error which happens when an envelope is too old or created in the future (the root cause is no time sync between nodes). The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, 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. ", - "url": "https://specs.status.im/stable/10#message-confirmations", - "relUrl": "/stable/10#message-confirmations" + "url": "https://specs.status.im/spec/10#message-confirmations", + "relUrl": "/spec/10#message-confirmations" },"23": { "doc": "10/WAKU-USAGE", "title": "Waku V1 extensions", "content": "Request historic messages . Sends a request for historic messages to a Mailserver. The Mailserver node MUST be a direct peer and MUST be marked as trusted (using waku_markTrustedPeer). The request does not wait for the response. It merely sends a peer-to-peer message to the Mailserver and it’s up to Mailserver to process it and start sending historic messages. The drawback of this approach is that it is impossible to tell which historic messages are the result of which request. It’s recommended to return messages from newest to oldest. To move further back in time, use cursor and limit. wakuext_requestMessages . Parameters: . | Object - The message request object: . | mailServerPeer - String: Mailserver’s enode address. | from - Number (optional): Lower bound of time range as unix timestamp, default is 24 hours back from now. | to - Number (optional): Upper bound of time range as unix timestamp, default is now. | limit - Number (optional): Limit the number of messages sent back, default is no limit. | cursor - String (optional): Used for paginated requests. | topics - Array: hex-encoded message topics. | symKeyID - String: an ID of a symmetric key used to authenticate with the Mailserver, derived from the Mailserver password. | . | . Returns: Boolean - returns true if the request was sent. The above topics is then converted into a bloom filter and then and sent to the Mailserver. ", - "url": "https://specs.status.im/stable/10#waku-v1-extensions", - "relUrl": "/stable/10#waku-v1-extensions" + "url": "https://specs.status.im/spec/10#waku-v1-extensions", + "relUrl": "/spec/10#waku-v1-extensions" },"24": { "doc": "10/WAKU-USAGE", "title": "Changelog", "content": "Version 0.1 . Released May 22, 2020 . | Created document | Forked from 3-whisper-usage | Change to keep Mailserver term consistent | Replaced Whisper references with Waku | Added Status options section | Updated Waku packets section to match Waku | Added that Batch Ack is marked for deprecation | Changed shh_generateSymKeyFromPassword to waku_generateSymKeyFromPassword . | Exists here | Exists here | . | Changed shh_markTrustedPeer to waku_markTrustedPeer . | Exists here | . | Changed shhext_requestMessages to wakuext_requestMessages . | Exists here | . | . ", - "url": "https://specs.status.im/stable/10#changelog", - "relUrl": "/stable/10#changelog" + "url": "https://specs.status.im/spec/10#changelog", + "relUrl": "/spec/10#changelog" },"25": { "doc": "10/WAKU-USAGE", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/10#copyright", - "relUrl": "/stable/10#copyright" + "url": "https://specs.status.im/spec/10#copyright", + "relUrl": "/spec/10#copyright" },"26": { "doc": "11/WAKU-MAILSERVER", "title": "11/WAKU-MAILSERVER", "content": "Version: 0.1 . Status: Stable . Authors: Adam Babik adam@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order) . | Status Waku Mailserver Specification . | Abstract | Mailserver . | Archiving messages | Requesting messages | Receiving historic messages | . | Security considerations . | Confidentiality | Altruistic and centralized operator risk | Privacy concerns | Denial-of-service | . | Changelog . | Version 0.1 | . | . | . ", - "url": "https://specs.status.im/stable/11", - "relUrl": "/stable/11" + "url": "https://specs.status.im/spec/11", + "relUrl": "/spec/11" },"27": { "doc": "11/WAKU-MAILSERVER", "title": "Abstract", "content": "Being mostly offline is an intrinsic property of mobile clients. They need to save network transfer and battery consumption to avoid spending too much money or constant charging. Waku protocol, on the other hand, is an online protocol. Messages are available in the Waku network only for short period of time calculate in seconds. Waku Mailserver is a specification that allows messages to be stored permanently and to allows the stored messages to be delivered to requesting client nodes, regardless if the messages are not available in the network due to the message TTL expiring. ", - "url": "https://specs.status.im/stable/11#abstract", - "relUrl": "/stable/11#abstract" + "url": "https://specs.status.im/spec/11#abstract", + "relUrl": "/spec/11#abstract" },"28": { "doc": "11/WAKU-MAILSERVER", "title": "Mailserver", "content": "From the network perspective, a Mailserver is just like any other Waku node. The only difference is that a Mailserver has the capability of archiving messages and delivering them to its peers on-demand. It is important to notice that a Mailserver will only handle requests from its direct peers and exchanged packets between a Mailserver and a peer are p2p messages. Archiving messages . A node which wants to provide Mailserver functionality MUST store envelopes from incoming message packets (Waku packet-code 0x01). The envelopes can be stored in any format, however they MUST be serialized and deserialized to the Waku envelope format. A Mailserver SHOULD store envelopes for all topics to be generally useful for any peer, however for specific use cases it MAY store envelopes for a subset of topics. Requesting messages . In order to request historic messages, a node MUST send a packet P2P Request (0x7e) to a peer providing Mailserver functionality. This packet requires one argument which MUST be a Waku envelope. In the Waku envelope’s payload section, there MUST be RLP-encoded information about the details of the request: . [ Lower, Upper, Bloom, Limit, Cursor ] . Lower: 4-byte wide unsigned integer (UNIX time in seconds; oldest requested envelope’s creation time) Upper: 4-byte wide unsigned integer (UNIX time in seconds; newest requested envelope’s creation time) Bloom: 64-byte wide array of Waku topics encoded in a bloom filter to filter envelopes Limit: 4-byte wide unsigned integer limiting the number of returned envelopes Cursor: an array of a cursor returned from the previous request (optional) . The Cursor field SHOULD be filled in if a number of envelopes between Lower and Upper is greater than Limit so that the requester can send another request using the obtained Cursor value. What exactly is in the Cursor is up to the implementation. The requester SHOULD NOT use a Cursor obtained from one Mailserver in a request to another Mailserver because the format or the result MAY be different. The envelope MUST be encrypted with a symmetric key agreed between the requester and the Mailserver. Receiving historic messages . 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 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. For a requester, to know that all messages have been sent by a Mailserver, it SHOULD handle P2P Request Complete code (0x7d). This code is followed by the following parameters: . [ RequestID, LastEnvelopeHash, Cursor ] . | RequestID: 32-byte wide array with a Keccak-256 hash of the envelope containing the original request | LastEnvelopeHash: 32-byte wide array with a Keccak-256 hash of the last sent envelope for the request | Cursor: an array of a cursor returned from the previous request (optional) | . If Cursor is not empty, it means that not all messages were sent due to the set Limit in the request. One or more consecutive requests MAY be sent with Cursor field filled in order to receive the rest of the messages. ", - "url": "https://specs.status.im/stable/11#mailserver", - "relUrl": "/stable/11#mailserver" + "url": "https://specs.status.im/spec/11#mailserver", + "relUrl": "/spec/11#mailserver" },"29": { "doc": "11/WAKU-MAILSERVER", "title": "Security considerations", "content": "Confidentiality . The node encrypts all Waku envelopes. A Mailserver node can not inspect their contents. Altruistic and centralized operator risk . In order to be useful, a Mailserver SHOULD be online most of time. That means users either have to be a bit tech-savvy to run their own node, or rely on someone else to run it for them. Currently, one of Status’s legal entities provides Mailservers in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research. A Status client SHOULD allow the Mailserver selection to be customizable. Privacy concerns . In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it will have access to the bloom filter of topics that the user is interested in, when it is online as well as many metadata like IP address. Denial-of-service . Since a Mailserver is delivering expired envelopes and has a direct TCP connection with the recipient, the recipient is vulnerable to DoS attacks from a malicious Mailserver node. ", - "url": "https://specs.status.im/stable/11#security-considerations", - "relUrl": "/stable/11#security-considerations" + "url": "https://specs.status.im/spec/11#security-considerations", + "relUrl": "/spec/11#security-considerations" },"30": { "doc": "11/WAKU-MAILSERVER", "title": "Changelog", "content": "Version 0.1 . Released May 22, 2020 . | Created document | Forked from 4-whisper-mailserver | Change to keep Mailserver term consistent | Replaced Whisper references with Waku | . ", - "url": "https://specs.status.im/stable/11#changelog", - "relUrl": "/stable/11#changelog" + "url": "https://specs.status.im/spec/11#changelog", + "relUrl": "/spec/11#changelog" },"31": { "doc": "11/WAKU-MAILSERVER", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/11#copyright", - "relUrl": "/stable/11#copyright" + "url": "https://specs.status.im/spec/11#copyright", + "relUrl": "/spec/11#copyright" },"32": { "doc": "12/IPFS gateway for Sticker Pack", "title": "12/IPFS gateway for Sticker Pack", @@ -356,26 +356,26 @@ "doc": "15/NOTIFICATIONS", "title": "15/NOTIFICATIONS", "content": " ", - "url": "https://specs.status.im/stable/15", - "relUrl": "/stable/15" + "url": "https://specs.status.im/spec/15", + "relUrl": "/spec/15" },"60": { "doc": "15/NOTIFICATIONS", "title": "Local Notifications", "content": "A client should implement local notifications to offer notifications for any event in the app without the privacy cost and dependency on third party services. This means that the client should run a background service to continuously or periodically check for updates. Android . Android allows running services on the device. When the user enables notifications, the client may start a ``Foreground Service`, and display a permanent notification indicating that the service is running, as required by Android guidelines. The service will simply keep the app from being killed by the system when it is in the background. The client will then be able to run in the background and display local notifications on events such as receiving a message in a one to one chat. To facilitate the implementation of local notifications, a node implementation such as status-go may provide a specific notification signal. Notifications are a separate process in Android, and interaction with a notification generates an Intent. To handle intents, the NewMessageSignalHandler may use a BroadcastReceiver, in order to update the state of local notifications when the user dismisses or tap a notification. If the user taps on a notification, the BroadcastReceiver generates a new intent to open the app should use universal links to get the user to the right place. iOS . We are not able to offer local notifications on iOS because there is no concept of services in iOS. It offers background updates but they’re not consistently triggered, and cannot be relied upon. The system decides when the background updates are triggered and the heuristics aren’t known. ", - "url": "https://specs.status.im/stable/15#local-notifications", - "relUrl": "/stable/15#local-notifications" + "url": "https://specs.status.im/spec/15#local-notifications", + "relUrl": "/spec/15#local-notifications" },"61": { "doc": "15/NOTIFICATIONS", "title": "Why is there no Push Notifications?", "content": "Push Notifications, as offered by Apple and Google are a privacy concern, they require a centralized service that is aware of who the notification needs to be delivered to. ", - "url": "https://specs.status.im/stable/15#why-is-there-no-push-notifications", - "relUrl": "/stable/15#why-is-there-no-push-notifications" + "url": "https://specs.status.im/spec/15#why-is-there-no-push-notifications", + "relUrl": "/spec/15#why-is-there-no-push-notifications" },"62": { "doc": "15/NOTIFICATIONS", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/15#copyright", - "relUrl": "/stable/15#copyright" + "url": "https://specs.status.im/spec/15#copyright", + "relUrl": "/spec/15#copyright" },"63": { "doc": "16/Keycard Usage for Wallet and Chat Keys", "title": "Table of Contents", @@ -458,470 +458,470 @@ "doc": "2/ACCOUNT", "title": "2/ACCOUNT", "content": "Version: 0.4 . Status: Stable . Authors: Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order) . ", - "url": "https://specs.status.im/stable/2", - "relUrl": "/stable/2" + "url": "https://specs.status.im/spec/2", + "relUrl": "/spec/2" },"77": { "doc": "2/ACCOUNT", "title": "Abstract", "content": "This specification explains what Status account is, and how a node establishes trust. ", - "url": "https://specs.status.im/stable/2#abstract", - "relUrl": "/stable/2#abstract" + "url": "https://specs.status.im/spec/2#abstract", + "relUrl": "/spec/2#abstract" },"78": { "doc": "2/ACCOUNT", "title": "Table of Contents", "content": ". | Abstract | Table of Contents | Introduction | Initial Key Generation . | Public/Private Keypairs | X3DH Prekey bundle creation | . | Account Broadcasting . | X3DH Prekey bundles | . | Optional Account additions . | ENS Username | . | Trust establishment . | Terms Glossary | Contact Discovery . | Public channels | Private 1:1 messages | . | Initial Key Exchange . | Bundles | . | Contact Verification . | Identicon | 3 word pseudonym / Whisper/Waku key fingerprint | ENS name | . | . | Public Key Serialization . | Basic Serialization Example | Public Key “Compression” Rationale | Key Encoding | Public Key Types | De/Serialization Process Flow . | Serialization Example | Deserialization Example | . | . | Security Considerations | Changelog . | Version 0.3 | . | . ", - "url": "https://specs.status.im/stable/2#table-of-contents", - "relUrl": "/stable/2#table-of-contents" + "url": "https://specs.status.im/spec/2#table-of-contents", + "relUrl": "/spec/2#table-of-contents" },"79": { "doc": "2/ACCOUNT", "title": "Introduction", "content": "The core concept of an account in Status is a set of cryptographic keypairs. Namely, the combination of the following: . | a Whisper/Waku chat identity keypair | a set of cryptocurrency wallet keypairs | . The node verifies or derives everything else associated with the contact from the above items, including: . | Ethereum address (future verification, currently the same base keypair) | 3 word mnemonic name | identicon | message signatures | . ", - "url": "https://specs.status.im/stable/2#introduction", - "relUrl": "/stable/2#introduction" + "url": "https://specs.status.im/spec/2#introduction", + "relUrl": "/spec/2#introduction" },"80": { "doc": "2/ACCOUNT", "title": "Initial Key Generation", "content": "Public/Private Keypairs . | An ECDSA (secp256k1 curve) public/private keypair MUST be generated via a BIP43 derived path from a BIP39 mnemonic seed phrase. | The default paths are defined as such: . | Whisper/Waku Chat Key (IK): m/43'/60'/1581'/0'/0 (post Multiaccount integration) . | following EIP1581 | . | Status Wallet paths: m/44'/60'/0'/0/i starting at i=0 . | following BIP44 | NOTE: this (i=0) is also the current (and only) path for Whisper/Waku key before Multiaccount integration | . | . | . X3DH Prekey bundle creation . | Status follows the X3DH prekey bundle scheme that Open Whisper Systems (not to be confused with the Whisper sub-protocol) outlines in their documentation with the following exceptions: . | Status does not publish one-time keys OPK or perform DH including them, because there are no central servers in the Status implementation. | . | A client MUST create X3DH prekey bundles, each defined by the following items: . | Identity Key: IK | Signed prekey: SPK | Prekey signature: Sig(IK, Encode(SPK)) | Timestamp | . | These bundles are made available in a variety of ways, as defined in section 2.1. | . ", - "url": "https://specs.status.im/stable/2#initial-key-generation", - "relUrl": "/stable/2#initial-key-generation" + "url": "https://specs.status.im/spec/2#initial-key-generation", + "relUrl": "/spec/2#initial-key-generation" },"81": { "doc": "2/ACCOUNT", "title": "Account Broadcasting", "content": ". | A user is responsible for broadcasting certain information publicly so that others may contact them. | . X3DH Prekey bundles . | A client SHOULD regenerate a new X3DH prekey bundle every 24 hours. This MAY be done in a lazy way, such that a client that does not come online past this time period does not regenerate or broadcast bundles. | The current bundle SHOULD be broadcast on a Whisper/Waku topic specific to his Identity Key, {IK}-contact-code, intermittently. This MAY be done every 6 hours. | A bundle SHOULD accompany every message sent. | TODO: retrieval of long-time offline users bundle via {IK}-contact-code | . ", - "url": "https://specs.status.im/stable/2#account-broadcasting", - "relUrl": "/stable/2#account-broadcasting" + "url": "https://specs.status.im/spec/2#account-broadcasting", + "relUrl": "/spec/2#account-broadcasting" },"82": { "doc": "2/ACCOUNT", "title": "Optional Account additions", "content": "ENS Username . | A user MAY register a public username on the Ethereum Name System (ENS). This username is a user-chosen subdomain of the stateofus.eth ENS registration that maps to their Whisper/Waku identity key (IK). | . ", - "url": "https://specs.status.im/stable/2#optional-account-additions", - "relUrl": "/stable/2#optional-account-additions" + "url": "https://specs.status.im/spec/2#optional-account-additions", + "relUrl": "/spec/2#optional-account-additions" },"83": { "doc": "2/ACCOUNT", "title": "Trust establishment", "content": "Trust establishment deals with users verifying they are communicating with who they think they are. Terms Glossary . | term | description | . | privkey | ECDSA secp256k1 private key | . | pubkey | ECDSA secp256k1 public key | . | Whisper/Waku key | pubkey for chat with HD derivation path m/43’/60’/1581’/0’/0 | . Contact Discovery . Public channels . | Public group channels in Status are a broadcast/subscription system. All public messages are encrypted with a symmetric key derived from the channel name, K_{pub,sym}, which is publicly known. | A public group channel’s symmetric key MUST creation must follow the web3 API’s web3.ssh.generateSymKeyFromPassword function | In order to post to a public group channel, a client MUST have a valid account created. | In order to listen to a public group channel, a client must subscribe to the channel name. The sender of a message is derived from the message’s signature. | Discovery of channel names is not currently part of the protocol, and is typically done out of band. If a channel name is used that has not been used, it will be created. | A client MUST sign the message otherwise it will be discarded by the recipients. | channel name specification: . | matches [a-z0-9\\-] | is not a public key | . | . Private 1:1 messages . This can be done in the following ways: . | scanning a user generated QR code | discovery through the Status app | asynchronous X3DH key exchange | public key via public channel listening . | status-react/src/status_im/contact_code/core.cljs | . | contact codes | decentralized storage (not implemented) | Whisper/Waku | . Initial Key Exchange . Bundles . | An X3DH prekey bundle is defined as (code): Identity // Identity key SignedPreKeys // a map of installation id to array of signed prekeys by that installation id Signature // Prekey signature Timestamp // When the bundle was lasted created locally . | include BundleContainer | . | a new bundle SHOULD be created at least every 12 hours | a node only generates a bundle when it is used | a bundle SHOULD be distributed on the contact code channel. This is the Whisper and Waku topic {IK}-contact-code, where IK is the hex encoded public key of the user, prefixed with 0x. The node encrypts the channel in the same way it encrypted public chats. | . Contact Verification . To verify that contact key information is as it should be, use the following. Identicon . A low-poly identicon is deterministically generated from the Whisper/Waku chat public key. This can be compared out of band to ensure the receiver’s public key is the one stored locally. 3 word pseudonym / Whisper/Waku key fingerprint . Status generates a deterministic 3-word random pseudonym from the Whisper/Waku chat public key. This pseudonym acts as a human readable fingerprint to the Whisper/Waku chat public key. This name also shows when viewing a contact’s public profile and in the chat UI. | implementation: gfycat | . 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. The user purchases this registration (currently by staking 10 SNT) and the node stores it on the Ethereum mainnet blockchain for public lookup. ", - "url": "https://specs.status.im/stable/2#trust-establishment", - "relUrl": "/stable/2#trust-establishment" + "url": "https://specs.status.im/spec/2#trust-establishment", + "relUrl": "/spec/2#trust-establishment" },"84": { "doc": "2/ACCOUNT", "title": "Public Key Serialization", "content": "Idiomatically known as “public key compression” and “public key decompression”. The node SHOULD provide functionality for the serialization and deserialization of public / chat keys. For maximum flexibility, when implementing this functionality, the node MUST support public keys encoded in a range of encoding formats, detailed below. Basic Serialization Example . In the example of a typical hexadecimal encoded elliptical curve (EC) public key (such as a secp256k1 pk), . 0x04261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6 . minor modification for compatibility and flexibility makes the key self-identifiable and easily parsable, . fe70104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6 . EC serialization and compact encoding produces a much smaller string representation of the original key. zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB . Public Key “Compression” Rationale . Serialized and compactly encoded (“compressed”) public keys have a number of UI / UX advantages over non-serialized less densely encoded public keys. Compressed public keys are smaller, and users may perceive them as less intimidating and less unnecessarily large. Compare the “compressed” and “uncompressed” version of the same public key from above example: . | 0xe70104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6 | zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB | . The user can transmit and share the same data, but at one third of the original size. 136 characters uncompressed vs 49 characters compressed, giving a significant character length reduction of 64%. The user client app MAY use the compressed public keys throughout the user interface. For example in the status-react implementation of the user interface the following places could take advantage of a significantly smaller public key: . | Onboarding > Choose a chat name | Profile > Header | Profile > Share icon > QR code popover | Invite friends url from Invite friends button and + -button > Invite friends | Other user Profile details | Profile details > Share icon > QR code popover | . In the case of QR codes a compressed public key can reduce the complexity of the derived codes: . | Uncompressed | Compressed | . | | | . Key Encoding . When implementing the pk de/serialization functionality, the node MUST use the multiformats/multibase encoding protocol to interpret incoming key data and to return key data in a desired encoding. The node SHOULD support the following multibase encoding formats. encoding, code, description, status identity, 0x00, 8-bit binary (encoder and decoder keeps data unmodified), default base2, 0, binary (01010101), candidate base8, 7, octal, draft base10, 9, decimal, draft base16, f, hexadecimal, default base16upper, F, hexadecimal, default base32hex, v, rfc4648 case-insensitive - no padding - highest char, candidate base32hexupper, V, rfc4648 case-insensitive - no padding - highest char, candidate base32hexpad, t, rfc4648 case-insensitive - with padding, candidate base32hexpadupper, T, rfc4648 case-insensitive - with padding, candidate base32, b, rfc4648 case-insensitive - no padding, default base32upper, B, rfc4648 case-insensitive - no padding, default base32pad, c, rfc4648 case-insensitive - with padding, candidate base32padupper, C, rfc4648 case-insensitive - with padding, candidate base32z, h, z-base-32 (used by Tahoe-LAFS), draft base36, k, base36 [0-9a-z] case-insensitive - no padding, draft base36upper, K, base36 [0-9a-z] case-insensitive - no padding, draft base58btc, z, base58 bitcoin, default base58flickr, Z, base58 flicker, candidate base64, m, rfc4648 no padding, default base64pad, M, rfc4648 with padding - MIME encoding, candidate base64url, u, rfc4648 no padding, default base64urlpad, U, rfc4648 with padding, default . Note this specification RECOMMENDs that implementations extend the standard multibase protocol to parse strings prepended with 0x as f hexadecimal encoded bytes. Implementing this recommendation will allow the node to correctly interpret traditionally identified hexadecimal strings (e.g. 0x1337c0de). Example: . 0xe70102261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc . SHOULD be interpreted as . fe70102261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc . This specification RECOMMENDs that the consuming service of the node uses a compact encoding type, such as base64 or base58 to allow for as short representations of the key as possible. Public Key Types . When implementing the pk de/serialization functionality, The node MUST support the multiformats/multicodec key type identifiers for the following public key type. | Name | Tag | Code | Description | . | secp256k1-pub | key | 0xe7 | Secp256k1 public key | . For a public key to be identifiable to the node the public key data MUST be prepended with the relevant multiformats/unsigned-varint formatted code. Example: . Below is a representation of an deserialized secp256k1 public key. 04 26 | 1c | 55 | 67 | 5e | 55 | ff | 25 ed | b5 | 0b | 34 | 5c | fb | 3a | 3f 35 | f6 | 07 | 12 | d2 | 51 | cb | aa ab | 97 | bd | 50 | 05 | 4c | 6e | bc 3c | d4 | e2 | 22 | 00 | c6 | 8d | af 74 | 93 | e1 | f8 | da | 6a | 19 | 0a 68 | a6 | 71 | e2 | d3 | 97 | 78 | 09 61 | 24 | 24 | c7 | c3 | 88 | 8b | c6 . The multicodec code for a secp256k1 public key is 0xe7. After parsing the code 0xe7 as a multiformats/uvarint, the byte value is 0xe7 0x01, prepending this to the public key results in the below representation. e7 | 01 | 04 26 | 1c | 55 | 67 | 5e | 55 | ff | 25 ed | b5 | 0b | 34 | 5c | fb | 3a | 3f 35 | f6 | 07 | 12 | d2 | 51 | cb | aa ab | 97 | bd | 50 | 05 | 4c | 6e | bc 3c | d4 | e2 | 22 | 00 | c6 | 8d | af 74 | 93 | e1 | f8 | da | 6a | 19 | 0a 68 | a6 | 71 | e2 | d3 | 97 | 78 | 09 61 | 24 | 24 | c7 | c3 | 88 | 8b | c6 . De/Serialization Process Flow . When implementing the pk de/serialization functionality, the node MUST be passed a multicodec identified public key, of the above supported types, encoded with a valid multibase identifier. This specification RECOMMENDs that the node also accept an encoding type parameter to encode the output data. This provides for the case where the user requires the de/serialization key to be in a different encoding to the encoding of the given key. Serialization Example . A hexadecimal encoded secp256k1 public chat key typically is represented as below: . 0x04261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6 . To be properly interpreted by the node for serialization the public key MUST be prepended with the multicodec uvarint code 0xea 0x01 and encoded with a valid multibase encoding, therefore giving the following: . fea0104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6 . If adhering to the specification recommendation to provide the user with an output encoding parameter, the above string would be passed to the node with the following multibase encoding identifier. In this example the output encoding is defined as base58 bitcoin. z . The return value in this case would be . zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB . Which after multibase decoding can be represented in bytes as below: . e7 | 01 | 02 26 | 1c | 55 | 67 | 5e | 55 | ff | 25 ed | b5 | 0b | 34 | 5c | fb | 3a | 3f 35 | f6 | 07 | 12 | d2 | 51 | cb | aa ab | 97 | bd | 50 | 05 | 4c | 6e | bc . Deserialization Example . For the user, the deserialization process is exactly the same as serialization with the exception that the user MUST provide a serialized public key for deserialization. Else the deserialization algorithm will fail. For further guidance on the implementation of public key de/serialization consult the status-go implementation and tests. ", - "url": "https://specs.status.im/stable/2#public-key-serialization", - "relUrl": "/stable/2#public-key-serialization" + "url": "https://specs.status.im/spec/2#public-key-serialization", + "relUrl": "/spec/2#public-key-serialization" },"85": { "doc": "2/ACCOUNT", "title": "Security Considerations", "content": "- . ", - "url": "https://specs.status.im/stable/2#security-considerations", - "relUrl": "/stable/2#security-considerations" + "url": "https://specs.status.im/spec/2#security-considerations", + "relUrl": "/spec/2#security-considerations" },"86": { "doc": "2/ACCOUNT", "title": "Changelog", "content": "Version 0.4 . Released June 24, 2020 . | Added details of public key serialization and deserialization | . Version 0.3 . Released May 22, 2020 . | Added language to include Waku in all relevant places | Change to keep Mailserver term consistent | Added clarification to Open Whisper Systems | . ", - "url": "https://specs.status.im/stable/2#changelog", - "relUrl": "/stable/2#changelog" + "url": "https://specs.status.im/spec/2#changelog", + "relUrl": "/spec/2#changelog" },"87": { "doc": "2/ACCOUNT", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/2#copyright", - "relUrl": "/stable/2#copyright" + "url": "https://specs.status.im/spec/2#copyright", + "relUrl": "/spec/2#copyright" },"88": { - "doc": "3/WHISPER-USAGE", - "title": "3/WHISPER-USAGE", - "content": "Version: 0.3 . Status: Stable . Authors: Adam Babik adam@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order) . | Abstract | Reason | Terminology | Whisper packets | Whisper node configuration | Handshake | Rate limiting | Keys management . | Contact code topic | Partitioned topic | Public chats | Group chat topic | . | Message encryption | Message confirmations | Whisper / Waku bridging | Whisper V6 extensions . | Request historic messages . | shhext_requestMessages | . | . | Changelog . | Version 0.3 | . | . ", - "url": "https://specs.status.im/stable/3", - "relUrl": "/stable/3" - },"89": { - "doc": "3/WHISPER-USAGE", - "title": "Abstract", - "content": "Status uses Whisper to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. This allows anyone to listen on a single channel. Additionally, since anyone can receive Whisper envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper. Finally, using an extension of Whisper provides the ability to do offline messaging. ", - "url": "https://specs.status.im/stable/3#abstract", - "relUrl": "/stable/3#abstract" - },"90": { - "doc": "3/WHISPER-USAGE", - "title": "Reason", - "content": "Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat. ", - "url": "https://specs.status.im/stable/3#reason", - "relUrl": "/stable/3#reason" - },"91": { - "doc": "3/WHISPER-USAGE", - "title": "Terminology", - "content": ". | Whisper node: an Ethereum node with Whisper V6 enabled (in the case of go-ethereum, it’s --shh option) | Whisper network: a group of Whisper nodes connected together through the internet connection and forming a graph | Message: a decrypted Whisper message | Offline message: an archived envelope | Envelope: an encrypted message with metadata like topic and Time-To-Live | . ", - "url": "https://specs.status.im/stable/3#terminology", - "relUrl": "/stable/3#terminology" - },"92": { - "doc": "3/WHISPER-USAGE", - "title": "Whisper packets", - "content": "| Packet Name | Code | EIP-627 | References | . | Status | 0 | ✔ | Handshake | . | Messages | 1 | ✔ | EIP-627 | . | PoW Requirement | 2 | ✔ | EIP-627 | . | Bloom Filter | 3 | ✔ | EIP-627 | . | Batch Ack | 11 | 𝘅 | Undocumented | . | Message Response | 12 | 𝘅 | Undocumented | . | P2P Sync Request | 123 | 𝘅 | Undocumented | . | P2P Sync Response | 124 | 𝘅 | Undocumented | . | P2P Request Complete | 125 | 𝘅 | 4/WHISPER-MAILSERVER | . | P2P Request | 126 | ✔ | 4/WHISPER-MAILSERVER | . | P2P Messages | 127 | ✔/𝘅 (EIP-627 supports only single envelope in a packet) | 4/WHISPER-MAILSERVER | . ", - "url": "https://specs.status.im/stable/3#whisper-packets", - "relUrl": "/stable/3#whisper-packets" - },"93": { - "doc": "3/WHISPER-USAGE", - "title": "Whisper node configuration", - "content": "A Whisper node must be properly configured to receive messages from Status clients. Nodes use Whisper’s Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: . | proof-of-work requirement not larger than 0.002 | time-to-live not lower than 10 (in seconds) | . ", - "url": "https://specs.status.im/stable/3#whisper-node-configuration", - "relUrl": "/stable/3#whisper-node-configuration" - },"94": { - "doc": "3/WHISPER-USAGE", - "title": "Handshake", - "content": "Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items: . [ protocolVersion, PoW, bloom, isLightNode, confirmationsEnabled, rateLimits ] . protocolVersion: version of the Whisper protocol PoW: minimum PoW accepted by the peer bloom: bloom filter of Whisper topic accepted by the peer isLightNode: when true, the peer won’t forward messages confirmationsEnabled: when true, the peer will send message confirmations rateLimits: is [ RateLimitIP, RateLimitPeerID, RateLimitTopic ] where each values is an integer with a number of accepted packets per second per IP, Peer ID, and Topic respectively . bloom, isLightNode, confirmationsEnabled, and rateLimits are all optional arguments in the handshake. However, if an optional field is specified, all optional fields preceding it MUST also be specified in order to be unambiguous. ", - "url": "https://specs.status.im/stable/3#handshake", - "relUrl": "/stable/3#handshake" - },"95": { - "doc": "3/WHISPER-USAGE", - "title": "Rate limiting", - "content": "In order to provide an optional very basic Denial-of-Service attack protection, each node SHOULD define its own rate limits. The rate limits SHOULD be applied on IPs, peer IDs, and envelope topics. Each node MAY decide to whitelist, i.e. do not rate limit, selected IPs or peer IDs. If a peer exceeds node’s rate limits, the connection between them MAY be dropped. Each node SHOULD broadcast its rate limits to its peers using rate limits packet code (0x14). The rate limits is RLP-encoded information: . [ IP limits, PeerID limits, Topic limits ] . IP limits: 4-byte wide unsigned integer PeerID limits: 4-byte wide unsigned integer Topic limits: 4-byte wide unsigned integer . The rate limits MAY also be sent as an optional parameter in the handshake. Each node SHOULD respect rate limits advertised by its peers. The number of packets SHOULD be throttled in order not to exceed peer’s rate limits. If the limit gets exceeded, the connection MAY be dropped by the peer. ", - "url": "https://specs.status.im/stable/3#rate-limiting", - "relUrl": "/stable/3#rate-limiting" - },"96": { - "doc": "3/WHISPER-USAGE", - "title": "Keys management", - "content": "The protocol requires a key (symmetric or asymmetric) for the following actions: . | signing & verifying messages (asymmetric key) | encrypting & decrypting messages (asymmetric or symmetric key). | . As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory. Keys management for PFS is described in 5/SECURE-TRANSPORT. The Status protocols uses a few particular Whisper topics to achieve its goals. Contact code topic . 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. Contact code topic MUST be created following the algorithm below: . contactCode := \"0x\" + hexEncode(activePublicKey) + \"-contact-code\" var hash []byte = keccak256(contactCode) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Partitioned topic . 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. Nodes use partitioned topics to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. Currently, nodes set the number of partitioned topics to 5000. They MUST be generated following the algorithm below: . var partitionsNum *big.Int = big.NewInt(5000) var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum) partitionTopic := \"contact-discovery-\" + strconv.FormatInt(partition.Int64(), 10) var hash []byte = keccak256(partitionTopic) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Public chats . A public chat MUST use a topic derived from a public chat name following the algorithm below: . var hash []byte hash = keccak256(name) topicLen = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Group chat topic . Group chats does not have a dedicated topic. All group chat messages (including membership updates) are sent as one-to-one messages to multiple recipients. Negotiated topic . When a client sends a one to one message to another client, it MUST listen to their negotiated topic. This is computed by generating a diffie-hellman key exchange between two members and taking the first four bytes of the SHA3-256 of the key generated. sharedKey, err := ecies.ImportECDSA(myPrivateKey).GenerateShared( ecies.ImportECDSAPublic(theirPublicKey), 16, 16, ) hexEncodedKey := hex.EncodeToString(sharedKey) var hash []byte = keccak256(hexEncodedKey) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . A client SHOULD send to the negotiated topic only if it has received a message from all the devices included in the conversation. Flow . To exchange messages with client B, a client A SHOULD: . | Listen to client’s B Contact Code Topic to retrieve their bundle information, including a list of active devices | Send a message on client’s B partitioned topic | Listen to the Negotiated Topic between A & B | Once client A receives a message from B, the Negotiated Topic SHOULD be used | . ", - "url": "https://specs.status.im/stable/3#keys-management", - "relUrl": "/stable/3#keys-management" - },"97": { - "doc": "3/WHISPER-USAGE", - "title": "Message encryption", - "content": "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. 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 JSON-RPC method of go-ethereum Whisper implementation. The node encrypts one-to-one messages using asymmetric encryption. ", - "url": "https://specs.status.im/stable/3#message-encryption", - "relUrl": "/stable/3#message-encryption" - },"98": { - "doc": "3/WHISPER-USAGE", - "title": "Message confirmations", - "content": "Sending a message is a complex process where many things can go wrong. Message confirmations tell a node that a message originating from it has been seen by its direct peers. A node MAY send a message confirmation for any batch of messages received in a packet Messages Code (0x01). 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 Message Response packet is more complex and is followed by a Versioned Message Response: . [ Version, Response] . Version: a version of the Message Response, equal to 1, Response: [ Hash, Errors ] where Hash is a keccak256 hash of the envelopes batch data (raw bytes) for which the confirmation is sent and Errors is a list of envelope errors when processing the batch. A single error contains [ Hash, Code, Description ] where Hash is a hash of the processed envelope, Code is an error code and Description is a descriptive error message. The supported codes: 1: means time sync error which happens when an envelope is too old or created in the future (the root cause is no time sync between nodes). The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, 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. ", - "url": "https://specs.status.im/stable/3#message-confirmations", - "relUrl": "/stable/3#message-confirmations" - },"99": { - "doc": "3/WHISPER-USAGE", - "title": "Whisper / Waku bridging", - "content": "In order to maintain compatibility between Whisper and Waku nodes, a Status network that implements both Whisper and Waku messaging protocols MUST have at least one node that is capable of discovering peers and implements Whisper v6, Waku V0 and Waku V1 specifications. Additionally, any Status network that implements both Whisper and Waku messaging protocols MUST implement bridging capabilities as detailed in Waku V1#Bridging. ", - "url": "https://specs.status.im/stable/3#whisper--waku-bridging", - "relUrl": "/stable/3#whisper--waku-bridging" - },"100": { - "doc": "3/WHISPER-USAGE", - "title": "Whisper V6 extensions", - "content": "Request historic messages . Sends a request for historic messages to a Mailserver. The Mailserver node MUST be a direct peer and MUST be marked as trusted (using shh_markTrustedPeer). The request does not wait for the response. It merely sends a peer-to-peer message to the Mailserver and it’s up to Mailserver to process it and start sending historic messages. The drawback of this approach is that it is impossible to tell which historic messages are the result of which request. It’s recommended to return messages from newest to oldest. To move further back in time, use cursor and limit. shhext_requestMessages . Parameters: . | Object - The message request object: . | mailServerPeer - String: Mailserver’s enode address. | from - Number (optional): Lower bound of time range as unix timestamp, default is 24 hours back from now. | to - Number (optional): Upper bound of time range as unix timestamp, default is now. | limit - Number (optional): Limit the number of messages sent back, default is no limit. | cursor - String (optional): Used for paginated requests. | topics - Array: hex-encoded message topics. | symKeyID - String: an ID of a symmetric key used to authenticate with the Mailserver, derived from Mailserver password. | . | . Returns: Boolean - returns true if the request was sent. The above topics is then converted into a bloom filter and then and sent to the Mailserver. ", - "url": "https://specs.status.im/stable/3#whisper-v6-extensions", - "relUrl": "/stable/3#whisper-v6-extensions" - },"101": { - "doc": "3/WHISPER-USAGE", - "title": "Changelog", - "content": "Version 0.3 . Released May 22, 2020 . | Added Whisper / Waku Bridging section | Change to keep Mailserver term consistent | . ", - "url": "https://specs.status.im/stable/3#changelog", - "relUrl": "/stable/3#changelog" - },"102": { - "doc": "3/WHISPER-USAGE", - "title": "Copyright", - "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/3#copyright", - "relUrl": "/stable/3#copyright" - },"103": { "doc": "3/WHISPER-USAGE", "title": "3/WHISPER-USAGE", "content": "Version: 0.3 . Status: Draft . Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im (alphabetical order) . | Abstract | Reason | Terminology | Whisper packets | Whisper node configuration | Handshake | Rate limiting | Keys management . | Contact code topic | Partitioned topic | Public chats | Group chat topic | . | Message encryption | Message confirmations | Whisper V6 extensions . | Request historic messages . | shhext_requestMessages | . | . | Changelog | . ", "url": "https://specs.status.im/draft/3", "relUrl": "/draft/3" - },"104": { + },"89": { "doc": "3/WHISPER-USAGE", "title": "Abstract", "content": "Status uses Whisper to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. This allows anyone to listen on a single channel. Additionally, since anyone can receive Whisper envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper. Finally, using an extension of Whisper provides the ability to do offline messaging. ", "url": "https://specs.status.im/draft/3#abstract", "relUrl": "/draft/3#abstract" - },"105": { + },"90": { "doc": "3/WHISPER-USAGE", "title": "Reason", "content": "Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat. ", "url": "https://specs.status.im/draft/3#reason", "relUrl": "/draft/3#reason" - },"106": { + },"91": { "doc": "3/WHISPER-USAGE", "title": "Terminology", "content": ". | Whisper node: an Ethereum node with Whisper V6 enabled (in the case of geth, it’s --shh option) | Whisper network: a group of Whisper nodes connected together through the internet connection and forming a graph | Message: a decrypted Whisper message | Offline message: an archived envelope | Envelope: an encrypted message with metadata like topic and Time-To-Live | . ", "url": "https://specs.status.im/draft/3#terminology", "relUrl": "/draft/3#terminology" - },"107": { + },"92": { "doc": "3/WHISPER-USAGE", "title": "Whisper packets", "content": "| Packet Name | Code | EIP-627 | References | . | Status | 0 | ✔ | Handshake | . | Messages | 1 | ✔ | EIP-627 | . | PoW Requirement | 2 | ✔ | EIP-627 | . | Bloom Filter | 3 | ✔ | EIP-627 | . | Batch Ack | 11 | 𝘅 | Undocumented | . | Message Response | 12 | 𝘅 | Undocumented | . | P2P Sync Request | 123 | 𝘅 | Undocumented | . | P2P Sync Response | 124 | 𝘅 | Undocumented | . | P2P Request Complete | 125 | 𝘅 | 4/WHISPER-MAILSERVER | . | P2P Request | 126 | ✔ | 4/WHISPER-MAILSERVER | . | P2P Messages | 127 | ✔/𝘅 (EIP-627 supports only single envelope in a packet) | 4/WHISPER-MAILSERVER | . ", "url": "https://specs.status.im/draft/3#whisper-packets", "relUrl": "/draft/3#whisper-packets" - },"108": { + },"93": { "doc": "3/WHISPER-USAGE", "title": "Whisper node configuration", "content": "A Whisper node must be properly configured to receive messages from Status clients. Whisper’s Proof Of Work algorithm is used to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: . | proof-of-work requirement not larger than 0.00001 | time-to-live not lower than 10 (in seconds) | any payload below 50000 bytes MUST be sent with a PoW Target of at least 0.002, in order to maintain backward compatibility with version 0.2 and Status app version 1.3 and below | . ", "url": "https://specs.status.im/draft/3#whisper-node-configuration", "relUrl": "/draft/3#whisper-node-configuration" - },"109": { + },"94": { "doc": "3/WHISPER-USAGE", "title": "Handshake", "content": "Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items: . [ protocolVersion, PoW, bloom, isLightNode, confirmationsEnabled, rateLimits ] . protocolVersion: version of the Whisper protocol PoW: minimum PoW accepted by the peer bloom: bloom filter of Whisper topic accepted by the peer isLightNode: when true, the peer won’t forward messages confirmationsEnabled: when true, the peer will send message confirmations rateLimits: is [ RateLimitIP, RateLimitPeerID, RateLimitTopic ] where each values is an integer with a number of accepted packets per second per IP, Peer ID, and Topic respectively . bloom, isLightNode, confirmationsEnabled, and rateLimits are all optional arguments in the handshake. However, if an optional field is specified, all optional fields preceding it MUST also be specified in order to be unambiguous. ", "url": "https://specs.status.im/draft/3#handshake", "relUrl": "/draft/3#handshake" - },"110": { + },"95": { "doc": "3/WHISPER-USAGE", "title": "Rate limiting", "content": "In order to provide an optional very basic Denial-of-Service attack protection, each node SHOULD define its own rate limits. The rate limits SHOULD be applied on IPs, peer IDs, and envelope topics. Each node MAY decide to whitelist, i.e. do not rate limit, selected IPs or peer IDs. If a peer exceeds node’s rate limits, the connection between them MAY be dropped. Each node SHOULD broadcast its rate limits to its peers using rate limits packet code (0x14). The rate limits is RLP-encoded information: . [ IP limits, PeerID limits, Topic limits ] . IP limits: 4-byte wide unsigned integer PeerID limits: 4-byte wide unsigned integer Topic limits: 4-byte wide unsigned integer . The rate limits MAY also be sent as an optional parameter in the handshake. Each node SHOULD respect rate limits advertised by its peers. The number of packets SHOULD be throttled in order not to exceed peer’s rate limits. If the limit gets exceeded, the connection MAY be dropped by the peer. ", "url": "https://specs.status.im/draft/3#rate-limiting", "relUrl": "/draft/3#rate-limiting" - },"111": { + },"96": { "doc": "3/WHISPER-USAGE", "title": "Keys management", "content": "The protocol requires a key (symmetric or asymmetric) for the following actions: . | signing & verifying messages (asymmetric key) | encrypting & decrypting messages (asymmetric or symmetric key). | . As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory. Keys management for PFS is described in 5/SECURE-TRANSPORT. The Status protocols uses a few particular Whisper topics to achieve its goals. Contact code topic . 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. Contact code topic MUST be created following the algorithm below: . contactCode := \"0x\" + hexEncode(activePublicKey) + \"-contact-code\" var hash []byte = keccak256(name) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Partitioned topic . 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. Nodes use partitioned topics to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. Currently, nodes set the number of partitioned topics to 5000. Partitioned topics MUST be generated following the algorithm below: . var partitionsNum *big.Int = big.NewInt(5000) var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum) partitionTopic := \"contact-discovery-\" + strconv.FormatInt(partition.Int64(), 10) var hash []byte = keccak256(partitionTopic) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Public chats . A public chat MUST use a topic derived from a public chat name following the algorithm below: . var hash []byte hash = keccak256(name) topicLen = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Group chat topic . Group chats does not have a dedicated topic. All group chat messages (including membership updates) are sent as one-to-one messages to multiple recipients. Negotiated topic . When a client sends a one to one message to another client, it MUST listen to their negotiated topic. This is computed by generating a diffie-hellman key exchange between two members and taking the first four bytes of the SHA3-256 of the key generated. sharedKey, err := ecies.ImportECDSA(myPrivateKey).GenerateShared( ecies.ImportECDSAPublic(theirPublicKey), 16, 16, ) hexEncodedKey := hex.EncodeToString(sharedKey) var hash []byte = keccak256(hexEncodedKey) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . A client SHOULD send to the negotiated topic only if it has received a message from all the devices included in the conversation. Flow . To exchange messages with client B, a client A SHOULD: . | Listen to client’s B Contact Code Topic to retrieve their bundle information, including a list of active devices | Send a message on client’s B partitioned topic | Listen to the Negotiated Topic between A & B | Once client A receives a message from B, the Negotiated Topic SHOULD be used | . ", "url": "https://specs.status.im/draft/3#keys-management", "relUrl": "/draft/3#keys-management" - },"112": { + },"97": { "doc": "3/WHISPER-USAGE", "title": "Message encryption", "content": "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. 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 JSON-RPC method of go-ethereum Whisper implementation. The node encrypts one-to-one messages using asymmetric encryption. ", "url": "https://specs.status.im/draft/3#message-encryption", "relUrl": "/draft/3#message-encryption" - },"113": { + },"98": { "doc": "3/WHISPER-USAGE", "title": "Message confirmations", "content": "Sending a message is a complex process where many things can go wrong. Message confirmations tell a node that a message originating from it has been seen by its direct peers. A node MAY send a message confirmation for any batch of messages received in a packet Messages Code (0x01). 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 Message Response packet is more complex and is followed by a Versioned Message Response: . [ Version, Response] . Version: a version of the Message Response, equal to 1, Response: [ Hash, Errors ] where Hash is a keccak256 hash of the envelopes batch data (raw bytes) for which the confirmation is sent and Errors is a list of envelope errors when processing the batch. A single error contains [ Hash, Code, Description ] where Hash is a hash of the processed envelope, Code is an error code and Description is a descriptive error message. The supported codes: 1: means time sync error which happens when an envelope is too old or created in the future (the root cause is no time sync between nodes). The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, 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. ", "url": "https://specs.status.im/draft/3#message-confirmations", "relUrl": "/draft/3#message-confirmations" - },"114": { + },"99": { "doc": "3/WHISPER-USAGE", "title": "Whisper V6 extensions", "content": "Request historic messages . Sends a request for historic messages to a Mailserver. The Mailserver node MUST be a direct peer and MUST be marked as trusted (using shh_markTrustedPeer). The request does not wait for the response. It merely sends a peer-to-peer message to the Mailserver and it’s up to Mailserver to process it and start sending historic messages. The drawback of this approach is that it is impossible to tell which historic messages are the result of which request. It’s recommended to return messages from newest to oldest. To move further back in time, use cursor and limit. shhext_requestMessages . Parameters: . | Object - The message request object: . | mailServerPeer - String: Mailserver’s enode address. | from - Number (optional): Lower bound of time range as unix timestamp, default is 24 hours back from now. | to - Number (optional): Upper bound of time range as unix timestamp, default is now. | limit - Number (optional): Limit the number of messages sent back, default is no limit. | cursor - String (optional): Used for paginated requests. | topics - Array: hex-encoded message topics. | symKeyID - String: an ID of a symmetric key to authenticate to Mailserver, derived from Mailserver password. | . | . Returns: Boolean - returns true if the request was sent. The above topics is then converted into a bloom filter and then and sent to the Mailserver. ", "url": "https://specs.status.im/draft/3#whisper-v6-extensions", "relUrl": "/draft/3#whisper-v6-extensions" - },"115": { + },"100": { "doc": "3/WHISPER-USAGE", "title": "Changelog", "content": "0.3 . | Updated minimum PoW to 0.00001 0.2 . | Document created | . ", "url": "https://specs.status.im/draft/3#changelog", "relUrl": "/draft/3#changelog" - },"116": { + },"101": { "doc": "3/WHISPER-USAGE", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", "url": "https://specs.status.im/draft/3#copyright", "relUrl": "/draft/3#copyright" + },"102": { + "doc": "3/WHISPER-USAGE", + "title": "3/WHISPER-USAGE", + "content": "Version: 0.3 . Status: Stable . Authors: Adam Babik adam@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order) . | Abstract | Reason | Terminology | Whisper packets | Whisper node configuration | Handshake | Rate limiting | Keys management . | Contact code topic | Partitioned topic | Public chats | Group chat topic | . | Message encryption | Message confirmations | Whisper / Waku bridging | Whisper V6 extensions . | Request historic messages . | shhext_requestMessages | . | . | Changelog . | Version 0.3 | . | . ", + "url": "https://specs.status.im/spec/3", + "relUrl": "/spec/3" + },"103": { + "doc": "3/WHISPER-USAGE", + "title": "Abstract", + "content": "Status uses Whisper to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. This allows anyone to listen on a single channel. Additionally, since anyone can receive Whisper envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper. Finally, using an extension of Whisper provides the ability to do offline messaging. ", + "url": "https://specs.status.im/spec/3#abstract", + "relUrl": "/spec/3#abstract" + },"104": { + "doc": "3/WHISPER-USAGE", + "title": "Reason", + "content": "Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat. ", + "url": "https://specs.status.im/spec/3#reason", + "relUrl": "/spec/3#reason" + },"105": { + "doc": "3/WHISPER-USAGE", + "title": "Terminology", + "content": ". | Whisper node: an Ethereum node with Whisper V6 enabled (in the case of go-ethereum, it’s --shh option) | Whisper network: a group of Whisper nodes connected together through the internet connection and forming a graph | Message: a decrypted Whisper message | Offline message: an archived envelope | Envelope: an encrypted message with metadata like topic and Time-To-Live | . ", + "url": "https://specs.status.im/spec/3#terminology", + "relUrl": "/spec/3#terminology" + },"106": { + "doc": "3/WHISPER-USAGE", + "title": "Whisper packets", + "content": "| Packet Name | Code | EIP-627 | References | . | Status | 0 | ✔ | Handshake | . | Messages | 1 | ✔ | EIP-627 | . | PoW Requirement | 2 | ✔ | EIP-627 | . | Bloom Filter | 3 | ✔ | EIP-627 | . | Batch Ack | 11 | 𝘅 | Undocumented | . | Message Response | 12 | 𝘅 | Undocumented | . | P2P Sync Request | 123 | 𝘅 | Undocumented | . | P2P Sync Response | 124 | 𝘅 | Undocumented | . | P2P Request Complete | 125 | 𝘅 | 4/WHISPER-MAILSERVER | . | P2P Request | 126 | ✔ | 4/WHISPER-MAILSERVER | . | P2P Messages | 127 | ✔/𝘅 (EIP-627 supports only single envelope in a packet) | 4/WHISPER-MAILSERVER | . ", + "url": "https://specs.status.im/spec/3#whisper-packets", + "relUrl": "/spec/3#whisper-packets" + },"107": { + "doc": "3/WHISPER-USAGE", + "title": "Whisper node configuration", + "content": "A Whisper node must be properly configured to receive messages from Status clients. Nodes use Whisper’s Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings: . | proof-of-work requirement not larger than 0.002 | time-to-live not lower than 10 (in seconds) | . ", + "url": "https://specs.status.im/spec/3#whisper-node-configuration", + "relUrl": "/spec/3#whisper-node-configuration" + },"108": { + "doc": "3/WHISPER-USAGE", + "title": "Handshake", + "content": "Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items: . [ protocolVersion, PoW, bloom, isLightNode, confirmationsEnabled, rateLimits ] . protocolVersion: version of the Whisper protocol PoW: minimum PoW accepted by the peer bloom: bloom filter of Whisper topic accepted by the peer isLightNode: when true, the peer won’t forward messages confirmationsEnabled: when true, the peer will send message confirmations rateLimits: is [ RateLimitIP, RateLimitPeerID, RateLimitTopic ] where each values is an integer with a number of accepted packets per second per IP, Peer ID, and Topic respectively . bloom, isLightNode, confirmationsEnabled, and rateLimits are all optional arguments in the handshake. However, if an optional field is specified, all optional fields preceding it MUST also be specified in order to be unambiguous. ", + "url": "https://specs.status.im/spec/3#handshake", + "relUrl": "/spec/3#handshake" + },"109": { + "doc": "3/WHISPER-USAGE", + "title": "Rate limiting", + "content": "In order to provide an optional very basic Denial-of-Service attack protection, each node SHOULD define its own rate limits. The rate limits SHOULD be applied on IPs, peer IDs, and envelope topics. Each node MAY decide to whitelist, i.e. do not rate limit, selected IPs or peer IDs. If a peer exceeds node’s rate limits, the connection between them MAY be dropped. Each node SHOULD broadcast its rate limits to its peers using rate limits packet code (0x14). The rate limits is RLP-encoded information: . [ IP limits, PeerID limits, Topic limits ] . IP limits: 4-byte wide unsigned integer PeerID limits: 4-byte wide unsigned integer Topic limits: 4-byte wide unsigned integer . The rate limits MAY also be sent as an optional parameter in the handshake. Each node SHOULD respect rate limits advertised by its peers. The number of packets SHOULD be throttled in order not to exceed peer’s rate limits. If the limit gets exceeded, the connection MAY be dropped by the peer. ", + "url": "https://specs.status.im/spec/3#rate-limiting", + "relUrl": "/spec/3#rate-limiting" + },"110": { + "doc": "3/WHISPER-USAGE", + "title": "Keys management", + "content": "The protocol requires a key (symmetric or asymmetric) for the following actions: . | signing & verifying messages (asymmetric key) | encrypting & decrypting messages (asymmetric or symmetric key). | . As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory. Keys management for PFS is described in 5/SECURE-TRANSPORT. The Status protocols uses a few particular Whisper topics to achieve its goals. Contact code topic . 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. Contact code topic MUST be created following the algorithm below: . contactCode := \"0x\" + hexEncode(activePublicKey) + \"-contact-code\" var hash []byte = keccak256(contactCode) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Partitioned topic . 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. Nodes use partitioned topics to broadcast private messages efficiently. By selecting a number of topic, it is possible to balance efficiency and privacy. Currently, nodes set the number of partitioned topics to 5000. They MUST be generated following the algorithm below: . var partitionsNum *big.Int = big.NewInt(5000) var partition *big.Int = big.NewInt(0).Mod(publicKey.X, partitionsNum) partitionTopic := \"contact-discovery-\" + strconv.FormatInt(partition.Int64(), 10) var hash []byte = keccak256(partitionTopic) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Public chats . A public chat MUST use a topic derived from a public chat name following the algorithm below: . var hash []byte hash = keccak256(name) topicLen = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . Group chat topic . Group chats does not have a dedicated topic. All group chat messages (including membership updates) are sent as one-to-one messages to multiple recipients. Negotiated topic . When a client sends a one to one message to another client, it MUST listen to their negotiated topic. This is computed by generating a diffie-hellman key exchange between two members and taking the first four bytes of the SHA3-256 of the key generated. sharedKey, err := ecies.ImportECDSA(myPrivateKey).GenerateShared( ecies.ImportECDSAPublic(theirPublicKey), 16, 16, ) hexEncodedKey := hex.EncodeToString(sharedKey) var hash []byte = keccak256(hexEncodedKey) var topicLen int = 4 if len(hash) < topicLen { topicLen = len(hash) } var topic [4]byte for i = 0; i < topicLen; i++ { topic[i] = hash[i] } . A client SHOULD send to the negotiated topic only if it has received a message from all the devices included in the conversation. Flow . To exchange messages with client B, a client A SHOULD: . | Listen to client’s B Contact Code Topic to retrieve their bundle information, including a list of active devices | Send a message on client’s B partitioned topic | Listen to the Negotiated Topic between A & B | Once client A receives a message from B, the Negotiated Topic SHOULD be used | . ", + "url": "https://specs.status.im/spec/3#keys-management", + "relUrl": "/spec/3#keys-management" + },"111": { + "doc": "3/WHISPER-USAGE", + "title": "Message encryption", + "content": "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. 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 JSON-RPC method of go-ethereum Whisper implementation. The node encrypts one-to-one messages using asymmetric encryption. ", + "url": "https://specs.status.im/spec/3#message-encryption", + "relUrl": "/spec/3#message-encryption" + },"112": { + "doc": "3/WHISPER-USAGE", + "title": "Message confirmations", + "content": "Sending a message is a complex process where many things can go wrong. Message confirmations tell a node that a message originating from it has been seen by its direct peers. A node MAY send a message confirmation for any batch of messages received in a packet Messages Code (0x01). 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 Message Response packet is more complex and is followed by a Versioned Message Response: . [ Version, Response] . Version: a version of the Message Response, equal to 1, Response: [ Hash, Errors ] where Hash is a keccak256 hash of the envelopes batch data (raw bytes) for which the confirmation is sent and Errors is a list of envelope errors when processing the batch. A single error contains [ Hash, Code, Description ] where Hash is a hash of the processed envelope, Code is an error code and Description is a descriptive error message. The supported codes: 1: means time sync error which happens when an envelope is too old or created in the future (the root cause is no time sync between nodes). The drawback of sending message confirmations is that it increases the noise in the network because for each sent message, 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. ", + "url": "https://specs.status.im/spec/3#message-confirmations", + "relUrl": "/spec/3#message-confirmations" + },"113": { + "doc": "3/WHISPER-USAGE", + "title": "Whisper / Waku bridging", + "content": "In order to maintain compatibility between Whisper and Waku nodes, a Status network that implements both Whisper and Waku messaging protocols MUST have at least one node that is capable of discovering peers and implements Whisper v6, Waku V0 and Waku V1 specifications. Additionally, any Status network that implements both Whisper and Waku messaging protocols MUST implement bridging capabilities as detailed in Waku V1#Bridging. ", + "url": "https://specs.status.im/spec/3#whisper--waku-bridging", + "relUrl": "/spec/3#whisper--waku-bridging" + },"114": { + "doc": "3/WHISPER-USAGE", + "title": "Whisper V6 extensions", + "content": "Request historic messages . Sends a request for historic messages to a Mailserver. The Mailserver node MUST be a direct peer and MUST be marked as trusted (using shh_markTrustedPeer). The request does not wait for the response. It merely sends a peer-to-peer message to the Mailserver and it’s up to Mailserver to process it and start sending historic messages. The drawback of this approach is that it is impossible to tell which historic messages are the result of which request. It’s recommended to return messages from newest to oldest. To move further back in time, use cursor and limit. shhext_requestMessages . Parameters: . | Object - The message request object: . | mailServerPeer - String: Mailserver’s enode address. | from - Number (optional): Lower bound of time range as unix timestamp, default is 24 hours back from now. | to - Number (optional): Upper bound of time range as unix timestamp, default is now. | limit - Number (optional): Limit the number of messages sent back, default is no limit. | cursor - String (optional): Used for paginated requests. | topics - Array: hex-encoded message topics. | symKeyID - String: an ID of a symmetric key used to authenticate with the Mailserver, derived from Mailserver password. | . | . Returns: Boolean - returns true if the request was sent. The above topics is then converted into a bloom filter and then and sent to the Mailserver. ", + "url": "https://specs.status.im/spec/3#whisper-v6-extensions", + "relUrl": "/spec/3#whisper-v6-extensions" + },"115": { + "doc": "3/WHISPER-USAGE", + "title": "Changelog", + "content": "Version 0.3 . Released May 22, 2020 . | Added Whisper / Waku Bridging section | Change to keep Mailserver term consistent | . ", + "url": "https://specs.status.im/spec/3#changelog", + "relUrl": "/spec/3#changelog" + },"116": { + "doc": "3/WHISPER-USAGE", + "title": "Copyright", + "content": "Copyright and related rights waived via CC0. ", + "url": "https://specs.status.im/spec/3#copyright", + "relUrl": "/spec/3#copyright" },"117": { "doc": "4/WHISPER-MAILSERVER", "title": "4/WHISPER-MAILSERVER", "content": "Version: 0.3 . Status: Stable . Authors: Adam Babik adam@status.im, Oskar Thorén oskar@status.im (alphabetical order) . | Abstract | Mailserver . | Archiving messages | Requesting messages | Receiving historic messages | . | Security considerations . | Confidentiality | Altruistic and centralized operator risk | Privacy concerns | Denial-of-service | . | Changelog . | Version 0.3 | . | . ", - "url": "https://specs.status.im/stable/4", - "relUrl": "/stable/4" + "url": "https://specs.status.im/spec/4", + "relUrl": "/spec/4" },"118": { "doc": "4/WHISPER-MAILSERVER", "title": "Abstract", "content": "Being mostly offline is an intrinsic property of mobile clients. They need to save network transfer and battery consumption to avoid spending too much money or constant charging. Whisper protocol, on the other hand, is an online protocol. Messages are available in the Whisper network only for short period of time calculate in seconds. Whisper Mailserver is a Whisper extension that allows to store messages permanently and deliver them to the clients even though they are already not available in the network and expired. ", - "url": "https://specs.status.im/stable/4#abstract", - "relUrl": "/stable/4#abstract" + "url": "https://specs.status.im/spec/4#abstract", + "relUrl": "/spec/4#abstract" },"119": { "doc": "4/WHISPER-MAILSERVER", "title": "Mailserver", "content": "From the network perspective, Mailserver is just like any other Whisper node. The only difference is that it has a capability of archiving messages and delivering them to its peers on-demand. It is important to notice that Mailserver will only handle requests from its direct peers and exchanged packets between Mailserver and a peer are p2p messages. Archiving messages . A node which wants to provide Mailserver functionality MUST store envelopes from incoming message packets (Whisper packet-code 0x01). The envelopes can be stored in any format, however they MUST be serialized and deserialized to the Whisper envelope format. A Mailserver SHOULD store envelopes for all topics to be generally useful for any peer, however for specific use cases it MAY store envelopes for a subset of topics. Requesting messages . In order to request historic messages, a node MUST send a packet P2P Request (0x7e) to a peer providing Mailserver functionality. This packet requires one argument which MUST be a Whisper envelope. In the Whisper envelope’s payload section, there MUST be RLP-encoded information about the details of the request: . [ Lower, Upper, Bloom, Limit, Cursor ] . Lower: 4-byte wide unsigned integer (UNIX time in seconds; oldest requested envelope’s creation time) Upper: 4-byte wide unsigned integer (UNIX time in seconds; newest requested envelope’s creation time) Bloom: 64-byte wide array of Whisper topics encoded in a bloom filter to filter envelopes Limit: 4-byte wide unsigned integer limiting the number of returned envelopes Cursor: an array of a cursor returned from the previous request (optional) . The Cursor field SHOULD be filled in if a number of envelopes between Lower and Upper is greater than Limit so that the requester can send another request using the obtained Cursor value. What exactly is in the Cursor is up to the implementation. The requester SHOULD NOT use a Cursor obtained from one Mailserver in a request to another Mailserver because the format or the result MAY be different. The envelope MUST be encrypted with a symmetric key agreed between the requester and Mailserver. Receiving historic messages . 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 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. For a requester, to know that all messages have been sent by Mailserver, it SHOULD handle P2P Request Complete code (0x7d). This code is followed by the following parameters: . [ RequestID, LastEnvelopeHash, Cursor ] . RequestID: 32-byte wide array with a Keccak-256 hash of the envelope containing the original request LastEnvelopeHash: 32-byte wide array with a Keccak-256 hash of the last sent envelope for the request Cursor: an array of a cursor returned from the previous request (optional) . If Cursor is not empty, it means that not all messages were sent due to the set Limit in the request. One or more consecutive requests MAY be sent with Cursor field filled in order to receive the rest of the messages. ", - "url": "https://specs.status.im/stable/4#mailserver", - "relUrl": "/stable/4#mailserver" + "url": "https://specs.status.im/spec/4#mailserver", + "relUrl": "/spec/4#mailserver" },"120": { "doc": "4/WHISPER-MAILSERVER", "title": "Security considerations", "content": "Confidentiality . The node encrypts all Whisper envelopes. A Mailserver node can not inspect their contents. Altruistic and centralized operator risk . In order to be useful, a Mailserver SHOULD be online most of the time. That means users either have to be a bit tech-savvy to run their own node, or rely on someone else to run it for them. Currently, one of Status’s legal entities provides Mailservers in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research. A Status client SHOULD allow the Mailserver selection to be customizable. Privacy concerns . In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it will have access to the bloom filter of topics that the user is interested in, when it is online as well as many metadata like IP address. Denial-of-service . Since a Mailserver is delivering expired envelopes and has a direct TCP connection with the recipient, the recipient is vulnerable to DoS attacks from a malicious Mailserver node. ", - "url": "https://specs.status.im/stable/4#security-considerations", - "relUrl": "/stable/4#security-considerations" + "url": "https://specs.status.im/spec/4#security-considerations", + "relUrl": "/spec/4#security-considerations" },"121": { "doc": "4/WHISPER-MAILSERVER", "title": "Changelog", "content": "Version 0.3 . Released May 22, 2020 . | Change to keep Mailserver term consistent | . ", - "url": "https://specs.status.im/stable/4#changelog", - "relUrl": "/stable/4#changelog" + "url": "https://specs.status.im/spec/4#changelog", + "relUrl": "/spec/4#changelog" },"122": { "doc": "4/WHISPER-MAILSERVER", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/4#copyright", - "relUrl": "/stable/4#copyright" + "url": "https://specs.status.im/spec/4#copyright", + "relUrl": "/spec/4#copyright" },"123": { "doc": "5/SECURE-TRANSPORT", "title": "5/SECURE-TRANSPORT", "content": "Version: 0.3 . Status: Stable . Authors: Andrea Piana andreap@status.im, Pedro Pombeiro pedro@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Dean Eigenmann dean@status.im . ", - "url": "https://specs.status.im/stable/5", - "relUrl": "/stable/5" + "url": "https://specs.status.im/spec/5", + "relUrl": "/spec/5" },"124": { "doc": "5/SECURE-TRANSPORT", "title": "Abstract", "content": "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 and Double Ratchet specifications, with some adaptations to operate in a decentralized environment. ", - "url": "https://specs.status.im/stable/5#abstract", - "relUrl": "/stable/5#abstract" + "url": "https://specs.status.im/spec/5#abstract", + "relUrl": "/spec/5#abstract" },"125": { "doc": "5/SECURE-TRANSPORT", "title": "Table of Contents", "content": ". | Abstract | Table of Contents | Introduction . | Definitions | Design Requirements | Conventions | Transport Layer | User flow for 1-to-1 communications . | Account generation | Account recovery | . | . | Messaging . | End-to-end encryption | Prekeys | Bundle retrieval | 1:1 chat contact request . | Initial key exchange flow (X3DH) | Double Ratchet | . | . | Security Considerations | Session management . | Abstract | Introduction | Initialization | Concurrent sessions | Re-keying | Multi-device support | Pairing | Sending messages to a paired group | Account recovery | Partitioned devices | . | Changelog . | Version 0.3 | . | . ", - "url": "https://specs.status.im/stable/5#table-of-contents", - "relUrl": "/stable/5#table-of-contents" + "url": "https://specs.status.im/spec/5#table-of-contents", + "relUrl": "/spec/5#table-of-contents" },"126": { "doc": "5/SECURE-TRANSPORT", "title": "Introduction", "content": "This document describes how nodes establish a secure channel, and how various conversational security properties are achieved. Definitions . | Perfect Forward Secrecy is a feature of specific key-agreement protocols which provide assurances that 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. | . Design Requirements . | Confidentiality: The adversary should not be able to learn what data is being exchanged between two Status clients. | Authenticity: The adversary should not be able to cause either endpoint of a Status 1:1 chat to accept data from any third party as though it came from the other endpoint. | Forward Secrecy: The adversary should not be able to learn what data was exchanged between two Status clients if, at some later time, the adversary compromises one or both of the endpoint devices. | Integrity: The adversary should not be able to cause either endpoint of a Status 1:1 chat to accept data that has been tampered with. | . All of these properties are ensured by the use of Signal’s Double Ratchet . Conventions . Types used in this specification are defined using Protobuf. Transport Layer . Whisper and Waku serves as the transport layers for the Status chat protocol. User flow for 1-to-1 communications . Account generation . See Account specification . Account recovery . 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, 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. ", - "url": "https://specs.status.im/stable/5#introduction", - "relUrl": "/stable/5#introduction" + "url": "https://specs.status.im/spec/5#introduction", + "relUrl": "/spec/5#introduction" },"127": { "doc": "5/SECURE-TRANSPORT", "title": "Messaging", "content": "All 1:1 and group chat messaging in Status is subject to end-to-end encryption to provide users with a strong degree of privacy and security. Public chat messages are publicly readable by anyone since there’s no permission model for who is participating in a public chat. The rest of this document is purely about 1:1 and private group chat. Private group chat largely reduces to 1:1 chat, since there’s a secure channel between each pair-wise participant. End-to-end encryption . End-to-end encryption (E2EE) takes place between two clients. The main cryptographic protocol is a Status implementation of the Double Ratchet protocol, which is in turn derived from the Off-the-Record protocol, using a different ratchet. The transport protocol subsequently encrypt the message payload - Whisper/Waku (see section Transport Layer) -, using symmetric key encryption. Furthermore, Status uses the concept of prekeys (through the use of 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: . | Whisper/Waku . | AES-256-GCM | ECIES | ECDSA | KECCAK-256 | . | X3DH . | Elliptic curve Diffie-Hellman key exchange (secp256k1) | KECCAK-256 | ECDSA | ECIES | . | Double Ratchet . | HMAC-SHA-256 as MAC | Elliptic curve Diffie-Hellman key exchange (Curve25519) | AES-256-CTR with HMAC-SHA-256 and IV derived alongside an encryption key | . The node achieves key derivation using HKDF. | . Prekeys . Every client initially generates some key material which is stored locally: . | Identity keypair based on secp256k1 - IK | A signed prekey based on secp256k1 - SPK | A prekey signature - Sig(IK, Encode(SPK)) | . More details can be found in the X3DH Prekey bundle creation section of 2/ACCOUNT. Prekey bundles can be extracted from any user’s messages, or found via searching for their specific topic, {IK}-contact-code. TODO: See below on bundle retrieval, this seems like enhancement and parameter for recommendation . Bundle retrieval . 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, nodes typically use a shared server to store bundles and allow other users to download them upon request. Given Status’ goal of decentralization, Status chat clients cannot rely on the same type of infrastructure and must achieve the same result using other means. By growing order of convenience and security, the considered approaches are: . | contact codes; | public and one-to-one chats; | QR codes; | ENS record; | Decentralized permanent storage (e.g. Swarm, IPFS). | Whisper/Waku | . 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. 1:1 chat contact request . There are two phases in the initial negotiation of a 1:1 chat: . | Identity verification (e.g., face-to-face contact exchange through QR code, Identicon matching). A QR code serves two purposes simultaneously - identity verification and initial bundle retrieval; | Asynchronous initial key exchange, using X3DH. | . For more information on account generation and trust establishment, see 2/ACCOUNT . Initial key exchange flow (X3DH) . Section 3 of the X3DH protocol describes the initial key exchange flow, with some additional context: . | The users’ identity keys IK_A and IK_B correspond to their respective Status chat public keys; | Since it is not possible to guarantee that a prekey will be used only once in a decentralized world, the one-time prekey OPK_B is not used in this scenario; | Nodes do not send Bundles to a centralized server, but instead served in a decentralized way as described in bundle retrieval. | . Alice retrieves Bob’s prekey bundle, however it is not specific to Alice. It contains: . (protobuf) . // X3DH prekey bundle message Bundle { bytes identity = 1; map<string,SignedPreKey> signed_pre_keys = 2; bytes signature = 4; int64 timestamp = 5; } . | identity: Identity key IK_B | signed_pre_keys: Signed prekey SPK_B for each device, indexed by installation-id | signature: Prekey signature Sig(IK_B, Encode(SPK_B)) | timestamp: When the bundle was created locally | . (protobuf) . message SignedPreKey { bytes signed_pre_key = 1; uint32 version = 2; } . The signature is generated by sorting installation-id in lexicographical order, and concatenating the signed-pre-key and version: . installation-id-1signed-pre-key1version1installation-id2signed-pre-key2-version-2 . Double Ratchet . 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 for more details. The initial message sent by Alice to Bob is sent as a top-level ProtocolMessage (protobuf) containing a map of DirectMessageProtocol indexed by installation-id (protobuf): . message ProtocolMessage { string installation_id = 2; repeated Bundle bundles = 3; // One to one message, encrypted, indexed by installation_id map<string,DirectMessageProtocol> direct_message = 101; // Public chats, not encrypted bytes public_message = 102; } . | bundles: a sequence of bundles | installation_id: the installation id of the sender | direct_message is a map of DirectMessageProtocol indexed by installation-id | public_message: unencrypted public chat message. | . message DirectMessageProtocol { X3DHHeader X3DH_header = 1; DRHeader DR_header = 2; DHHeader DH_header = 101; // Encrypted payload bytes payload = 3; } . | X3DH_header: the X3DHHeader field in DirectMessageProtocol contains: . (protobuf) . message X3DHHeader { bytes key = 1; bytes id = 4; } . | key: Alice’s ephemeral key EK_A; | id: Identifier stating which of Bob’s prekeys Alice used, in this case Bob’s bundle signed prekey. | . Alice’s identity key IK_A is sent at the transport layer level (Whisper/Waku); . | DR_header: Double ratchet header (protobuf). Used when Bob’s public bundle is available: message DRHeader { bytes key = 1; uint32 n = 2; uint32 pn = 3; bytes id = 4; } . | key: Alice’s current ratchet public key (as mentioned in DR spec section 2.2); | n: number of the message in the sending chain; | pn: length of the previous sending chain; | id: Bob’s bundle ID. | . | DH_header: Diffie-Helman header (used when Bob’s bundle is not available): (protobuf) message DHHeader { bytes key = 1; } . | key: Alice’s compressed ephemeral public key. | . | payload: . | if a bundle is available, contains payload encrypted with the Double Ratchet algorithm; | otherwise, payload encrypted with output key of DH exchange (no Perfect Forward Secrecy). | . | . ", - "url": "https://specs.status.im/stable/5#messaging", - "relUrl": "/stable/5#messaging" + "url": "https://specs.status.im/spec/5#messaging", + "relUrl": "/spec/5#messaging" },"128": { "doc": "5/SECURE-TRANSPORT", "title": "Security Considerations", "content": "The same considerations apply as in section 4 of the X3DH spec and section 6 of the Double Ratchet spec, with some additions detailed below. ", - "url": "https://specs.status.im/stable/5#security-considerations", - "relUrl": "/stable/5#security-considerations" + "url": "https://specs.status.im/spec/5#security-considerations", + "relUrl": "/spec/5#security-considerations" },"129": { "doc": "5/SECURE-TRANSPORT", "title": "Session management", "content": "A node identifies a peer by two pieces of data: . 1) An installation-id which is generated upon creating a new account in the Status application 2) Their identity Whisper/Waku key . Initialization . A node initializes a new session once a successful X3DH exchange has taken place. Subsequent messages will use the established session until re-keying is necessary. Concurrent sessions . If 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 . On receiving a bundle from a given peer with a higher version, the old bundle SHOULD be marked as expired and a new session SHOULD be established on the next message sent. Multi-device support . 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, 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 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 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/ . Pairing . 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. 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 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. Removal of paired devices is a manual step that needs to be applied on each device, and consist simply in disabling the device, at which point pairing information will not be propagated anymore. Sending messages to a paired group . When sending a message, the peer will send a message to other installation-id that they have seen. The node caps the number of devices to 3, ordered by last activity. The node sends messages using pairwise encryption, including their own devices. Account recovery . Account recovery is no different from adding a new device, and it is handled in exactly the same way. Partitioned devices . In some cases (i.e. account recovery when no other pairing device is available, device not paired), it is possible that a device will receive a message that is not targeted to its own installation-id. In this case an empty message containing bundle information is sent back, which will notify the receiving end of including this device in any further communication. ", - "url": "https://specs.status.im/stable/5#session-management", - "relUrl": "/stable/5#session-management" + "url": "https://specs.status.im/spec/5#session-management", + "relUrl": "/spec/5#session-management" },"130": { "doc": "5/SECURE-TRANSPORT", "title": "Changelog", "content": "Version 0.3 . Released May 22, 2020 . | Added language to include Waku in all relevant places | . ", - "url": "https://specs.status.im/stable/5#changelog", - "relUrl": "/stable/5#changelog" + "url": "https://specs.status.im/spec/5#changelog", + "relUrl": "/spec/5#changelog" },"131": { "doc": "5/SECURE-TRANSPORT", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/5#copyright", - "relUrl": "/stable/5#copyright" + "url": "https://specs.status.im/spec/5#copyright", + "relUrl": "/spec/5#copyright" },"132": { - "doc": "6/PAYLOADS", - "title": "6/PAYLOADS", - "content": "Version: 0.3 . Status: Stable . Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Oskar Thorén oskar@status.im (alphabetical order) . ", - "url": "https://specs.status.im/stable/6", - "relUrl": "/stable/6" - },"133": { - "doc": "6/PAYLOADS", - "title": "Abstract", - "content": "This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases. The payloads aims to be flexible enough to support messaging but also cases described in the Status Whitepaper as well as various clients created using different technologies. ", - "url": "https://specs.status.im/stable/6#abstract", - "relUrl": "/stable/6#abstract" - },"134": { - "doc": "6/PAYLOADS", - "title": "Table of Contents", - "content": ". | Abstract | Table of Contents | Introduction | Payload wrapper | Encoding | Types of messages . | Message . | Payload | Payload | Content types . | Sticker content type | . | Message types | Clock vs Timestamp and message ordering | Chats | . | Contact Update . | Payload | Contact update | . | SyncInstallationContact . | Payload | . | SyncInstallationPublicChat . | Payload | . | PairInstallation . | Payload | . | MembershipUpdateMessage and MembershipUpdateEvent | . | Upgradability | Security Considerations | Changelog . | Version 0.3 | . | . ", - "url": "https://specs.status.im/stable/6#table-of-contents", - "relUrl": "/stable/6#table-of-contents" - },"135": { - "doc": "6/PAYLOADS", - "title": "Introduction", - "content": "This document describes the payload format and some special considerations. ", - "url": "https://specs.status.im/stable/6#introduction", - "relUrl": "/stable/6#introduction" - },"136": { - "doc": "6/PAYLOADS", - "title": "Payload wrapper", - "content": "The node wraps all payloads in a protobuf record record: . message ApplicationMetadataMessage { bytes signature = 1; bytes payload = 2; Type type = 3; enum Type { UNKNOWN = 0; CHAT_MESSAGE = 1; CONTACT_UPDATE = 2; MEMBERSHIP_UPDATE_MESSAGE = 3; PAIR_INSTALLATION = 4; SYNC_INSTALLATION = 5; REQUEST_ADDRESS_FOR_TRANSACTION = 6; ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION = 7; DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION = 8; REQUEST_TRANSACTION = 9; SEND_TRANSACTION = 10; DECLINE_REQUEST_TRANSACTION = 11; SYNC_INSTALLATION_CONTACT = 12; SYNC_INSTALLATION_ACCOUNT = 13; SYNC_INSTALLATION_PUBLIC_CHAT = 14; CONTACT_CODE_ADVERTISEMENT = 15; PUSH_NOTIFICATION_REGISTRATION = 16; PUSH_NOTIFICATION_REGISTRATION_RESPONSE = 17; PUSH_NOTIFICATION_QUERY = 18; PUSH_NOTIFICATION_QUERY_RESPONSE = 19; PUSH_NOTIFICATION_REQUEST = 20; PUSH_NOTIFICATION_RESPONSE = 21; } } . signature is the bytes of the signed SHA3-256 of the payload, signed with the key of the author of the message. The node needs the signature to validate authorship of the message, so that the message can be relayed to third parties. If a signature is not present, but an author is provided by a layer below, the message is not to be relayed to third parties, and it is considered plausibly deniable. payload is the protobuf encoded content of the message, with the corresponding type set. ", - "url": "https://specs.status.im/stable/6#payload-wrapper", - "relUrl": "/stable/6#payload-wrapper" - },"137": { - "doc": "6/PAYLOADS", - "title": "Encoding", - "content": "The node encodes the payload using Protobuf . ", - "url": "https://specs.status.im/stable/6#encoding", - "relUrl": "/stable/6#encoding" - },"138": { - "doc": "6/PAYLOADS", - "title": "Types of messages", - "content": "Message . The type ChatMessage represents a chat message exchanged between clients. Payload . The protobuf description is: . message ChatMessage { // Lamport timestamp of the chat message uint64 clock = 1; // Unix timestamps in milliseconds, currently not used as we use Whisper/Waku as more reliable, but here // so that we don't rely on it uint64 timestamp = 2; // Text of the message string text = 3; // Id of the message that we are replying to string response_to = 4; // Ens name of the sender string ens_name = 5; // Chat id, this field is symmetric for public-chats and private group chats, // but asymmetric in case of one-to-ones, as the sender will use the chat-id // of the received, while the receiver will use the chat-id of the sender. // Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order string chat_id = 6; // The type of message (public/one-to-one/private-group-chat) MessageType message_type = 7; // The type of the content of the message ContentType content_type = 8; oneof payload { StickerMessage sticker = 9; } enum MessageType { UNKNOWN_MESSAGE_TYPE = 0; ONE_TO_ONE = 1; PUBLIC_GROUP = 2; PRIVATE_GROUP = 3; // Only local SYSTEM_MESSAGE_PRIVATE_GROUP = 4;} enum ContentType { UNKNOWN_CONTENT_TYPE = 0; TEXT_PLAIN = 1; STICKER = 2; STATUS = 3; EMOJI = 4; TRANSACTION_COMMAND = 5; // Only local SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP = 6; } } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | The clock of the chat | . | 2 | timestamp | uint64 | The sender timestamp at message creation | . | 3 | text | string | The content of the message | . | 4 | response_to | string | The ID of the message replied to | . | 5 | ens_name | string | The ENS name of the user sending the message | . | 6 | chat_id | string | The local ID of the chat the message is sent to | . | 7 | message_type | MessageType | The type of message, different for one-to-one, public or group chats | . | 8 | content_type | ContentType | The type of the content of the message | . | 9 | payload | Sticker|nil | The payload of the message based on the content type | . Content types . A node requires content types for a proper interpretation of incoming messages. Not each message is plain text but may carry different information. The following content types MUST be supported: . | TEXT_PLAIN identifies a message which content is a plaintext. | . There are other content types that MAY be implemented by the client: . | STICKER | STATUS | EMOJI | TRANSACTION_COMMAND | . Mentions . A mention MUST be represented as a string with the @0xpk format, where pk is the public key of the user account to be mentioned, within the text field of a message with content_type TEXT_PLAIN. A message MAY contain more than one mention. This specification RECOMMENDs that the application does not require the user to enter the entire pk. This specification RECOMMENDs that the application allows the user to create a mention by typing @ followed by the related ENS or 3-word pseudonym. This specification RECOMMENDs that the application provides the user auto-completion functionality to create a mention. For better user experience, the client SHOULD display a known ens name or the 3-word pseudonym corresponding to the key instead of the pk. Sticker content type . A ChatMessage with STICKER Content/Type MUST also specify the ID of the Pack and the Hash of the pack, in the Sticker field of ChatMessage . message StickerMessage { string hash = 1; int32 pack = 2; } . Message types . 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 and 10/WAKU-USAGE. The following messages types MUST be supported: . | ONE_TO_ONE is a message to the public group | PUBLIC_GROUP is a private message | PRIVATE_GROUP is a message to the private group. | . Clock vs Timestamp and message ordering . If a user sends a new message before the messages sent while the user was offline are received, the new message is supposed to be displayed last in a chat. This is where the basic algorithm of Lamport timestamp would fall short as it’s only meant to order causally related events. The status client therefore makes a “bid”, speculating that it will beat the current chat-timestamp, s.t. the status client’s Lamport timestamp format is: clock = max({timestamp}, chat_clock + 1)` . This will satisfy the Lamport requirement, namely: a -> b then T(a) < T(b) . timestamp MUST be Unix time calculated, when the 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. When there are messages available in a chat, the node calculates clock’s value based on the last received message in a particular chat: max(timeNowInMs, last-message-clock-value + 1). If there are no messages, clock is initialized with timestamp’s value. Messages with a clock greater than 120 seconds over the Whisper/Waku timestamp SHOULD be discarded, in order to avoid malicious users to increase the clock of a chat arbitrarily. Messages with a clock less than 120 seconds under the Whisper/Waku timestamp might indicate an attempt to insert messages in the chat history which is not distinguishable from a datasync layer re-transit event. A client MAY mark this messages with a warning to the user, or discard them. The node uses clock value for the message ordering. The algorithm used, and the distributed nature of the system produces casual ordering, which might produce counter-intuitive results in some edge cases. For example, when a user joins a public chat and sends a message before receiving the exist messages, their message clock value might be lower and the message will end up in the past when the historical messages are fetched. Chats . Chat is a structure that helps organize messages. It’s usually desired to display messages only from a single recipient, or a group of recipients at a time and chats help to achieve that. All incoming messages can be matched against a chat. The below table describes how to calculate a chat ID for each message type. | Message Type | Chat ID Calculation | Direction | Comment | . | PUBLIC_GROUP | chat ID is equal to a public channel name; it should equal chatId from the message | Incoming/Outgoing |   | . | ONE_TO_ONE | let P be a public key of the recipient; hex-encode(P) is a chat ID; use it as chatId value in the message | Outgoing |   | . | user-message | let P be a public key of message’s signature; hex-encode(P) is a chat ID; discard chat-id from message | Incoming | if there is no matched chat, it might be the first message from public key P; the node MAY discard the message or MAY create a new chat; Status official clients create a new chat | . | PRIVATE_GROUP | use chatId from the message | Incoming/Outgoing | find an existing chat by chatId; if none is found, the user is not a member of that chat or the user hasn’t joined that chat, the message MUST be discarded | . Contact Update . ContactUpdate is a message exchange to notify peers that either the user has been added as a contact, or that information about the sending user have changed. message ContactUpdate { uint64 clock = 1; string ens_name = 2; string profile_image = 3; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | The clock of the chat with the user | . | 2 | ens_name | string | The ENS name if set | . | 3 | profile_image | string | The base64 encoded profile picture of the user | . Contact update . A client SHOULD send a ContactUpdate to all the contacts each time: . | The ens_name has changed | A user edits the profile image | . A client SHOULD also periodically send a ContactUpdate to all the contacts, the interval is up to the client, the Status official client sends these updates every 48 hours. SyncInstallationContact . The node uses SyncInstallationContact messages to synchronize in a best-effort the contacts to other devices. message SyncInstallationContact { uint64 clock = 1; string id = 2; string profile_image = 3; string ens_name = 4; uint64 last_updated = 5; repeated string system_tags = 6; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | id | string | id of the contact synced | . | 3 | profile_image | string | base64 encoded profile picture of the user | . | 4 | ens_name | string | ENS name of the contact | . | 5 | array[string] | Array of system_tags for the user, this can currently be: \":contact/added\", \":contact/blocked\", \":contact/request-received\" |   | . SyncInstallationPublicChat . The node uses SyncInstallationPublicChat message to synchronize in a best-effort the public chats to other devices. message SyncInstallationPublicChat { uint64 clock = 1; string id = 2; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | id | string | id of the chat synced | . PairInstallation . The node uses PairInstallation messages to propagate information about a device to its paired devices. message PairInstallation { uint64 clock = 1; string installation_id = 2; string device_type = 3; string name = 4; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | installation_id | string | A randomly generated id that identifies this device | . | 3 | device_type | string | The OS of the device ios,android or desktop | . | 4 | name | string | The self-assigned name of the device | . MembershipUpdateMessage and MembershipUpdateEvent . MembershipUpdateEvent is a message used to propagate information about group membership changes in a group chat. The details are in the Group chats specs. ", - "url": "https://specs.status.im/stable/6#types-of-messages", - "relUrl": "/stable/6#types-of-messages" - },"139": { - "doc": "6/PAYLOADS", - "title": "Upgradability", - "content": "There are two ways to upgrade the protocol without breaking compatibility: . | A node always supports accretion | A node does not support deletion of existing fields or messages, which might break compatibility | . ", - "url": "https://specs.status.im/stable/6#upgradability", - "relUrl": "/stable/6#upgradability" - },"140": { - "doc": "6/PAYLOADS", - "title": "Security Considerations", - "content": "- . ", - "url": "https://specs.status.im/stable/6#security-considerations", - "relUrl": "/stable/6#security-considerations" - },"141": { - "doc": "6/PAYLOADS", - "title": "Changelog", - "content": "Version 0.3 . Released May 22, 2020 . | Added language to include Waku in all relevant places | . ", - "url": "https://specs.status.im/stable/6#changelog", - "relUrl": "/stable/6#changelog" - },"142": { - "doc": "6/PAYLOADS", - "title": "Copyright", - "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/6#copyright", - "relUrl": "/stable/6#copyright" - },"143": { "doc": "6/PAYLOADS", "title": "6/PAYLOADS", "content": "Version: 0.5 . Status: Draft . Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order) . ", "url": "https://specs.status.im/draft/6", "relUrl": "/draft/6" - },"144": { + },"133": { "doc": "6/PAYLOADS", "title": "Abstract", "content": "This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases. The payloads aims to be flexible enough to support messaging but also cases described in the Status Whitepaper as well as various clients created using different technologies. ", "url": "https://specs.status.im/draft/6#abstract", "relUrl": "/draft/6#abstract" - },"145": { + },"134": { "doc": "6/PAYLOADS", "title": "Table of Contents", "content": ". | Abstract | Table of Contents | Introduction | Payload wrapper | Encoding | Types of messages . | Message . | Payload | Payload | Content types . | Sticker content type | Image content type | Audio content type | . | Message types | Clock vs Timestamp and message ordering | Chats | . | Contact Update . | Payload | Contact update | . | EmojiReaction | SyncInstallationContact . | Payload | . | SyncInstallationPublicChat . | Payload | . | PairInstallation . | Payload | . | MembershipUpdateMessage and MembershipUpdateEvent | . | Upgradability | Security Considerations | Changelog | Copyright | . ", "url": "https://specs.status.im/draft/6#table-of-contents", "relUrl": "/draft/6#table-of-contents" - },"146": { + },"135": { "doc": "6/PAYLOADS", "title": "Introduction", "content": "This document describes the payload format and some special considerations. ", "url": "https://specs.status.im/draft/6#introduction", "relUrl": "/draft/6#introduction" - },"147": { + },"136": { "doc": "6/PAYLOADS", "title": "Payload wrapper", "content": "The node wraps all payloads in a protobuf record record: . message StatusProtocolMessage { bytes signature = 4001; bytes payload = 4002; } . signature is the bytes of the signed SHA3-256 of the payload, signed with the key of the author of the message. The node needs the signature to validate authorship of the message, so that the message can be relayed to third parties. If a signature is not present, but an author is provided by a layer below, the message is not to be relayed to third parties, and it is considered plausibly deniable. ", "url": "https://specs.status.im/draft/6#payload-wrapper", "relUrl": "/draft/6#payload-wrapper" - },"148": { + },"137": { "doc": "6/PAYLOADS", "title": "Encoding", "content": "The node encodes the payload using Protobuf . ", "url": "https://specs.status.im/draft/6#encoding", "relUrl": "/draft/6#encoding" - },"149": { + },"138": { "doc": "6/PAYLOADS", "title": "Types of messages", "content": "Message . The type ChatMessage represents a chat message exchanged between clients. Payload . The protobuf description is: . message ChatMessage { // Lamport timestamp of the chat message uint64 clock = 1; // Unix timestamps in milliseconds, currently not used as we use Whisper/Waku as more reliable, but here // so that we don't rely on it uint64 timestamp = 2; // Text of the message string text = 3; // Id of the message that we are replying to string response_to = 4; // Ens name of the sender string ens_name = 5; // Chat id, this field is symmetric for public-chats and private group chats, // but asymmetric in case of one-to-ones, as the sender will use the chat-id // of the received, while the receiver will use the chat-id of the sender. string chat_id = 6; // The type of message (public/one-to-one/private-group-chat) MessageType message_type = 7; // The type of the content of the message ContentType content_type = 8; oneof payload { StickerMessage sticker = 9; ImageMessage image = 10; AudioMessage audio = 11; } enum ContentType { UNKNOWN_CONTENT_TYPE = 0; TEXT_PLAIN = 1; STICKER = 2; STATUS = 3; EMOJI = 4; TRANSACTION_COMMAND = 5; // Only local SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP = 6; IMAGE = 7; AUDIO = 8; } } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | The clock of the chat | . | 2 | timestamp | uint64 | The sender timestamp at message creation | . | 3 | text | string | The content of the message | . | 4 | response_to | string | The ID of the message replied to | . | 5 | ens_name | string | The ENS name of the user sending the message | . | 6 | chat_id | string | The local ID of the chat the message is sent to | . | 7 | message_type | MessageType | The type of message, different for one-to-one, public or group chats | . | 8 | content_type | ContentType | The type of the content of the message | . | 9 | payload | Sticker I Image I Audio I nil | The payload of the message based on the content type | . Content types . A node requires content types for a proper interpretation of incoming messages. Not each message is plain text but may carry different information. The following content types MUST be supported: . | TEXT_PLAIN identifies a message which content is a plaintext. | . There are other content types that MAY be implemented by the client: . | STICKER | STATUS | EMOJI | TRANSACTION_COMMAND | IMAGE | AUDIO | . Mentions . A mention MUST be represented as a string with the @0xpk format, where pk is the public key of the user account to be mentioned, within the text field of a message with content_type TEXT_PLAIN. A message MAY contain more than one mention. This specification RECOMMENDs that the application does not require the user to enter the entire pk. This specification RECOMMENDs that the application allows the user to create a mention by typing @ followed by the related ENS or 3-word pseudonym. This specification RECOMMENDs that the application provides the user auto-completion functionality to create a mention. For better user experience, the client SHOULD display a known ens name or the 3-word pseudonym corresponding to the key instead of the pk. Sticker content type . A ChatMessage with STICKER Content/Type MUST also specify the ID of the Pack and the Hash of the pack, in the Sticker field of ChatMessage . message StickerMessage { string hash = 1; int32 pack = 2; } . Image content type . A ChatMessage with IMAGE Content/Type MUST also specify the payload of the image and the type. Clients MUST sanitize the payload before accessing its content, in particular: . | Clients MUST choose a secure decoder | Clients SHOULD strip metadata if present without parsing/decoding it | Clients SHOULD NOT add metadata/exif when sending an image file for privacy and security reasons | Clients MUST make sure that the transport layer constraints the size of the payload to limit they are able to handle securely | . message ImageMessage { bytes payload = 1; ImageType type = 2; enum ImageType { UNKNOWN_IMAGE_TYPE = 0; PNG = 1; JPEG = 2; WEBP = 3; GIF = 4; } } . Audio content type . A ChatMessage with AUDIO Content/Type MUST also specify the payload of the audio, the type and the duration in milliseconds (duration_ms). Clients MUST sanitize the payload before accessing its content, in particular: . | Clients MUST choose a secure decoder | Clients SHOULD strip metadata if present without parsing/decoding it | Clients SHOULD NOT add metadata/exif when sending an audio file for privacy and security reasons | Clients MUST make sure that the transport layer constraints the size of the payload to limit they are able to handle securely | . message AudioMessage { bytes payload = 1; AudioType type = 2; uint64 duration_ms = 3; enum AudioType { UNKNOWN_AUDIO_TYPE = 0; AAC = 1; AMR = 2; . Message types . 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 and 10/WAKU-USAGE. The following messages types MUST be supported: . | ONE_TO_ONE is a message to the public group | PUBLIC_GROUP is a private message | PRIVATE_GROUP is a message to the private group. | . enum MessageType { UNKNOWN_MESSAGE_TYPE = 0; ONE_TO_ONE = 1; PUBLIC_GROUP = 2; PRIVATE_GROUP = 3; // Only local SYSTEM_MESSAGE_PRIVATE_GROUP = 4; } . Clock vs Timestamp and message ordering . If a user sends a new message before the messages sent while the user was offline are received, the new message is supposed to be displayed last in a chat. This is where the basic algorithm of Lamport timestamp would fall short as it’s only meant to order causally related events. The status client therefore makes a “bid”, speculating that it will beat the current chat-timestamp, s.t. the status client’s Lamport timestamp format is: clock = max({timestamp}, chat_clock + 1)` . This will satisfy the Lamport requirement, namely: a -> b then T(a) < T(b) . timestamp MUST be Unix time calculated, when the 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. When there are messages available in a chat, the node calculates clock’s value based on the last received message in a particular chat: max(timeNowInMs, last-message-clock-value + 1). If there are no messages, clock is initialized with timestamp’s value. Messages with a clock greater than 120 seconds over the Whisper/Waku timestamp SHOULD be discarded, in order to avoid malicious users to increase the clock of a chat arbitrarily. Messages with a clock less than 120 seconds under the Whisper/Waku timestamp might indicate an attempt to insert messages in the chat history which is not distinguishable from a datasync layer re-transit event. A client MAY mark this messages with a warning to the user, or discard them. The node uses clock value for the message ordering. The algorithm used, and the distributed nature of the system produces casual ordering, which might produce counter-intuitive results in some edge cases. For example, when a user joins a public chat and sends a message before receiving the exist messages, their message clock value might be lower and the message will end up in the past when the historical messages are fetched. Chats . Chat is a structure that helps organize messages. It’s usually desired to display messages only from a single recipient, or a group of recipients at a time and chats help to achieve that. All incoming messages can be matched against a chat. The below table describes how to calculate a chat ID for each message type. | Message Type | Chat ID Calculation | Direction | Comment | . | PUBLIC_GROUP | chat ID is equal to a public channel name; it should equal chatId from the message | Incoming/Outgoing |   | . | ONE_TO_ONE | let P be a public key of the recipient; hex-encode(P) is a chat ID; use it as chatId value in the message | Outgoing |   | . | user-message | let P be a public key of message’s signature; hex-encode(P) is a chat ID; discard chat-id from message | Incoming | if there is no matched chat, it might be the first message from public key P; the node MAY discard the message or MAY create a new chat; Status official clients create a new chat | . | PRIVATE_GROUP | use chatId from the message | Incoming/Outgoing | find an existing chat by chatId; if none is found, the user is not a member of that chat or the user hasn’t joined that chat, the message MUST be discarded | . Contact Update . ContactUpdate is a message exchange to notify peers that either the user has been added as a contact, or that information about the sending user have changed. message ContactUpdate { uint64 clock = 1; string ens_name = 2; string profile_image = 3; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | The clock of the chat with the user | . | 2 | ens_name | string | The ENS name if set | . | 3 | profile_image | string | The base64 encoded profile picture of the user | . Contact update . A client SHOULD send a ContactUpdate to all the contacts each time: . | The ens_name has changed | 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. EmojiReaction . EmojiReactions represents a user’s “reaction” to a specific chat message. For more information about the concept of emoji reactions see Facebook Reactions. This specification RECOMMENDS that the UI/UX implementation of sending EmojiReactions requires only a single click operation, as users have an expectation that emoji reactions are effortless and simple to perform. message EmojiReaction { // clock Lamport timestamp of the chat message uint64 clock = 1; // chat_id the ID of the chat the message belongs to, for query efficiency the chat_id is stored in the db even though the // target message also stores the chat_id string chat_id = 2; // message_id the ID of the target message that the user wishes to react to string message_id = 3; // message_type is (somewhat confusingly) the ID of the type of chat the message belongs to MessageType message_type = 4; // type the ID of the emoji the user wishes to react with Type type = 5; enum Type { UNKNOWN_EMOJI_REACTION_TYPE = 0; LOVE = 1; THUMBS_UP = 2; THUMBS_DOWN = 3; LAUGH = 4; SAD = 5; ANGRY = 6; } // whether this is a retraction of a previously sent emoji bool retracted = 6; } . Clients MUST specify clock, chat_id, message_id, type and message_type. This specification RECOMMENDS that the UI/UX implementation of retracting an EmojiReactions requires only a single click operation, as users have an expectation that emoji reaction removals are effortless and simple to perform. SyncInstallationContact . The node uses SyncInstallationContact messages to synchronize in a best-effort the contacts to other devices. message SyncInstallationContact { uint64 clock = 1; string id = 2; string profile_image = 3; string ens_name = 4; uint64 last_updated = 5; repeated string system_tags = 6; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | id | string | id of the contact synced | . | 3 | profile_image | string | base64 encoded profile picture of the user | . | 4 | ens_name | string | ENS name of the contact | . | 5 | array[string] | Array of system_tags for the user, this can currently be: \":contact/added\", \":contact/blocked\", \":contact/request-received\" |   | . SyncInstallationPublicChat . The node uses SyncInstallationPublicChat message to synchronize in a best-effort the public chats to other devices. message SyncInstallationPublicChat { uint64 clock = 1; string id = 2; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | id | string | id of the chat synced | . PairInstallation . The node uses PairInstallation messages to propagate information about a device to its paired devices. message PairInstallation { uint64 clock = 1; string installation_id = 2; string device_type = 3; string name = 4; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | installation_id | string | A randomly generated id that identifies this device | . | 3 | device_type | string | The OS of the device ios,android or desktop | . | 4 | name | string | The self-assigned name of the device | . MembershipUpdateMessage and MembershipUpdateEvent . MembershipUpdateEvent is a message used to propagate information about group membership changes in a group chat. The details are in the Group chats specs. ", "url": "https://specs.status.im/draft/6#types-of-messages", "relUrl": "/draft/6#types-of-messages" - },"150": { + },"139": { "doc": "6/PAYLOADS", "title": "Upgradability", "content": "There are two ways to upgrade the protocol without breaking compatibility: . | A node always supports accretion | A node does not support deletion of existing fields or messages, which might break compatibility | . ", "url": "https://specs.status.im/draft/6#upgradability", "relUrl": "/draft/6#upgradability" - },"151": { + },"140": { "doc": "6/PAYLOADS", "title": "Security Considerations", "content": "- . ", "url": "https://specs.status.im/draft/6#security-considerations", "relUrl": "/draft/6#security-considerations" - },"152": { + },"141": { "doc": "6/PAYLOADS", "title": "Changelog", "content": "Version 0.5 . Released August 25, 2020 . | Added support for emoji reactions | . Version 0.4 . Released July 16, 2020 . | Added support for images | Added support for audio | . Version 0.3 . Released May 22, 2020 . | Added language to include Waku in all relevant places | . ", "url": "https://specs.status.im/draft/6#changelog", "relUrl": "/draft/6#changelog" - },"153": { + },"142": { "doc": "6/PAYLOADS", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", "url": "https://specs.status.im/draft/6#copyright", "relUrl": "/draft/6#copyright" + },"143": { + "doc": "6/PAYLOADS", + "title": "6/PAYLOADS", + "content": "Version: 0.3 . Status: Stable . Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Oskar Thorén oskar@status.im (alphabetical order) . ", + "url": "https://specs.status.im/spec/6", + "relUrl": "/spec/6" + },"144": { + "doc": "6/PAYLOADS", + "title": "Abstract", + "content": "This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases. The payloads aims to be flexible enough to support messaging but also cases described in the Status Whitepaper as well as various clients created using different technologies. ", + "url": "https://specs.status.im/spec/6#abstract", + "relUrl": "/spec/6#abstract" + },"145": { + "doc": "6/PAYLOADS", + "title": "Table of Contents", + "content": ". | Abstract | Table of Contents | Introduction | Payload wrapper | Encoding | Types of messages . | Message . | Payload | Payload | Content types . | Sticker content type | . | Message types | Clock vs Timestamp and message ordering | Chats | . | Contact Update . | Payload | Contact update | . | SyncInstallationContact . | Payload | . | SyncInstallationPublicChat . | Payload | . | PairInstallation . | Payload | . | MembershipUpdateMessage and MembershipUpdateEvent | . | Upgradability | Security Considerations | Changelog . | Version 0.3 | . | . ", + "url": "https://specs.status.im/spec/6#table-of-contents", + "relUrl": "/spec/6#table-of-contents" + },"146": { + "doc": "6/PAYLOADS", + "title": "Introduction", + "content": "This document describes the payload format and some special considerations. ", + "url": "https://specs.status.im/spec/6#introduction", + "relUrl": "/spec/6#introduction" + },"147": { + "doc": "6/PAYLOADS", + "title": "Payload wrapper", + "content": "The node wraps all payloads in a protobuf record record: . message ApplicationMetadataMessage { bytes signature = 1; bytes payload = 2; Type type = 3; enum Type { UNKNOWN = 0; CHAT_MESSAGE = 1; CONTACT_UPDATE = 2; MEMBERSHIP_UPDATE_MESSAGE = 3; PAIR_INSTALLATION = 4; SYNC_INSTALLATION = 5; REQUEST_ADDRESS_FOR_TRANSACTION = 6; ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION = 7; DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION = 8; REQUEST_TRANSACTION = 9; SEND_TRANSACTION = 10; DECLINE_REQUEST_TRANSACTION = 11; SYNC_INSTALLATION_CONTACT = 12; SYNC_INSTALLATION_ACCOUNT = 13; SYNC_INSTALLATION_PUBLIC_CHAT = 14; CONTACT_CODE_ADVERTISEMENT = 15; PUSH_NOTIFICATION_REGISTRATION = 16; PUSH_NOTIFICATION_REGISTRATION_RESPONSE = 17; PUSH_NOTIFICATION_QUERY = 18; PUSH_NOTIFICATION_QUERY_RESPONSE = 19; PUSH_NOTIFICATION_REQUEST = 20; PUSH_NOTIFICATION_RESPONSE = 21; } } . signature is the bytes of the signed SHA3-256 of the payload, signed with the key of the author of the message. The node needs the signature to validate authorship of the message, so that the message can be relayed to third parties. If a signature is not present, but an author is provided by a layer below, the message is not to be relayed to third parties, and it is considered plausibly deniable. payload is the protobuf encoded content of the message, with the corresponding type set. ", + "url": "https://specs.status.im/spec/6#payload-wrapper", + "relUrl": "/spec/6#payload-wrapper" + },"148": { + "doc": "6/PAYLOADS", + "title": "Encoding", + "content": "The node encodes the payload using Protobuf . ", + "url": "https://specs.status.im/spec/6#encoding", + "relUrl": "/spec/6#encoding" + },"149": { + "doc": "6/PAYLOADS", + "title": "Types of messages", + "content": "Message . The type ChatMessage represents a chat message exchanged between clients. Payload . The protobuf description is: . message ChatMessage { // Lamport timestamp of the chat message uint64 clock = 1; // Unix timestamps in milliseconds, currently not used as we use Whisper/Waku as more reliable, but here // so that we don't rely on it uint64 timestamp = 2; // Text of the message string text = 3; // Id of the message that we are replying to string response_to = 4; // Ens name of the sender string ens_name = 5; // Chat id, this field is symmetric for public-chats and private group chats, // but asymmetric in case of one-to-ones, as the sender will use the chat-id // of the received, while the receiver will use the chat-id of the sender. // Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order string chat_id = 6; // The type of message (public/one-to-one/private-group-chat) MessageType message_type = 7; // The type of the content of the message ContentType content_type = 8; oneof payload { StickerMessage sticker = 9; } enum MessageType { UNKNOWN_MESSAGE_TYPE = 0; ONE_TO_ONE = 1; PUBLIC_GROUP = 2; PRIVATE_GROUP = 3; // Only local SYSTEM_MESSAGE_PRIVATE_GROUP = 4;} enum ContentType { UNKNOWN_CONTENT_TYPE = 0; TEXT_PLAIN = 1; STICKER = 2; STATUS = 3; EMOJI = 4; TRANSACTION_COMMAND = 5; // Only local SYSTEM_MESSAGE_CONTENT_PRIVATE_GROUP = 6; } } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | The clock of the chat | . | 2 | timestamp | uint64 | The sender timestamp at message creation | . | 3 | text | string | The content of the message | . | 4 | response_to | string | The ID of the message replied to | . | 5 | ens_name | string | The ENS name of the user sending the message | . | 6 | chat_id | string | The local ID of the chat the message is sent to | . | 7 | message_type | MessageType | The type of message, different for one-to-one, public or group chats | . | 8 | content_type | ContentType | The type of the content of the message | . | 9 | payload | Sticker|nil | The payload of the message based on the content type | . Content types . A node requires content types for a proper interpretation of incoming messages. Not each message is plain text but may carry different information. The following content types MUST be supported: . | TEXT_PLAIN identifies a message which content is a plaintext. | . There are other content types that MAY be implemented by the client: . | STICKER | STATUS | EMOJI | TRANSACTION_COMMAND | . Mentions . A mention MUST be represented as a string with the @0xpk format, where pk is the public key of the user account to be mentioned, within the text field of a message with content_type TEXT_PLAIN. A message MAY contain more than one mention. This specification RECOMMENDs that the application does not require the user to enter the entire pk. This specification RECOMMENDs that the application allows the user to create a mention by typing @ followed by the related ENS or 3-word pseudonym. This specification RECOMMENDs that the application provides the user auto-completion functionality to create a mention. For better user experience, the client SHOULD display a known ens name or the 3-word pseudonym corresponding to the key instead of the pk. Sticker content type . A ChatMessage with STICKER Content/Type MUST also specify the ID of the Pack and the Hash of the pack, in the Sticker field of ChatMessage . message StickerMessage { string hash = 1; int32 pack = 2; } . Message types . 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 and 10/WAKU-USAGE. The following messages types MUST be supported: . | ONE_TO_ONE is a message to the public group | PUBLIC_GROUP is a private message | PRIVATE_GROUP is a message to the private group. | . Clock vs Timestamp and message ordering . If a user sends a new message before the messages sent while the user was offline are received, the new message is supposed to be displayed last in a chat. This is where the basic algorithm of Lamport timestamp would fall short as it’s only meant to order causally related events. The status client therefore makes a “bid”, speculating that it will beat the current chat-timestamp, s.t. the status client’s Lamport timestamp format is: clock = max({timestamp}, chat_clock + 1)` . This will satisfy the Lamport requirement, namely: a -> b then T(a) < T(b) . timestamp MUST be Unix time calculated, when the 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. When there are messages available in a chat, the node calculates clock’s value based on the last received message in a particular chat: max(timeNowInMs, last-message-clock-value + 1). If there are no messages, clock is initialized with timestamp’s value. Messages with a clock greater than 120 seconds over the Whisper/Waku timestamp SHOULD be discarded, in order to avoid malicious users to increase the clock of a chat arbitrarily. Messages with a clock less than 120 seconds under the Whisper/Waku timestamp might indicate an attempt to insert messages in the chat history which is not distinguishable from a datasync layer re-transit event. A client MAY mark this messages with a warning to the user, or discard them. The node uses clock value for the message ordering. The algorithm used, and the distributed nature of the system produces casual ordering, which might produce counter-intuitive results in some edge cases. For example, when a user joins a public chat and sends a message before receiving the exist messages, their message clock value might be lower and the message will end up in the past when the historical messages are fetched. Chats . Chat is a structure that helps organize messages. It’s usually desired to display messages only from a single recipient, or a group of recipients at a time and chats help to achieve that. All incoming messages can be matched against a chat. The below table describes how to calculate a chat ID for each message type. | Message Type | Chat ID Calculation | Direction | Comment | . | PUBLIC_GROUP | chat ID is equal to a public channel name; it should equal chatId from the message | Incoming/Outgoing |   | . | ONE_TO_ONE | let P be a public key of the recipient; hex-encode(P) is a chat ID; use it as chatId value in the message | Outgoing |   | . | user-message | let P be a public key of message’s signature; hex-encode(P) is a chat ID; discard chat-id from message | Incoming | if there is no matched chat, it might be the first message from public key P; the node MAY discard the message or MAY create a new chat; Status official clients create a new chat | . | PRIVATE_GROUP | use chatId from the message | Incoming/Outgoing | find an existing chat by chatId; if none is found, the user is not a member of that chat or the user hasn’t joined that chat, the message MUST be discarded | . Contact Update . ContactUpdate is a message exchange to notify peers that either the user has been added as a contact, or that information about the sending user have changed. message ContactUpdate { uint64 clock = 1; string ens_name = 2; string profile_image = 3; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | The clock of the chat with the user | . | 2 | ens_name | string | The ENS name if set | . | 3 | profile_image | string | The base64 encoded profile picture of the user | . Contact update . A client SHOULD send a ContactUpdate to all the contacts each time: . | The ens_name has changed | A user edits the profile image | . A client SHOULD also periodically send a ContactUpdate to all the contacts, the interval is up to the client, the Status official client sends these updates every 48 hours. SyncInstallationContact . The node uses SyncInstallationContact messages to synchronize in a best-effort the contacts to other devices. message SyncInstallationContact { uint64 clock = 1; string id = 2; string profile_image = 3; string ens_name = 4; uint64 last_updated = 5; repeated string system_tags = 6; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | id | string | id of the contact synced | . | 3 | profile_image | string | base64 encoded profile picture of the user | . | 4 | ens_name | string | ENS name of the contact | . | 5 | array[string] | Array of system_tags for the user, this can currently be: \":contact/added\", \":contact/blocked\", \":contact/request-received\" |   | . SyncInstallationPublicChat . The node uses SyncInstallationPublicChat message to synchronize in a best-effort the public chats to other devices. message SyncInstallationPublicChat { uint64 clock = 1; string id = 2; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | id | string | id of the chat synced | . PairInstallation . The node uses PairInstallation messages to propagate information about a device to its paired devices. message PairInstallation { uint64 clock = 1; string installation_id = 2; string device_type = 3; string name = 4; } . Payload . | Field | Name | Type | Description | . | 1 | clock | uint64 | clock value of the chat | . | 2 | installation_id | string | A randomly generated id that identifies this device | . | 3 | device_type | string | The OS of the device ios,android or desktop | . | 4 | name | string | The self-assigned name of the device | . MembershipUpdateMessage and MembershipUpdateEvent . MembershipUpdateEvent is a message used to propagate information about group membership changes in a group chat. The details are in the Group chats specs. ", + "url": "https://specs.status.im/spec/6#types-of-messages", + "relUrl": "/spec/6#types-of-messages" + },"150": { + "doc": "6/PAYLOADS", + "title": "Upgradability", + "content": "There are two ways to upgrade the protocol without breaking compatibility: . | A node always supports accretion | A node does not support deletion of existing fields or messages, which might break compatibility | . ", + "url": "https://specs.status.im/spec/6#upgradability", + "relUrl": "/spec/6#upgradability" + },"151": { + "doc": "6/PAYLOADS", + "title": "Security Considerations", + "content": "- . ", + "url": "https://specs.status.im/spec/6#security-considerations", + "relUrl": "/spec/6#security-considerations" + },"152": { + "doc": "6/PAYLOADS", + "title": "Changelog", + "content": "Version 0.3 . Released May 22, 2020 . | Added language to include Waku in all relevant places | . ", + "url": "https://specs.status.im/spec/6#changelog", + "relUrl": "/spec/6#changelog" + },"153": { + "doc": "6/PAYLOADS", + "title": "Copyright", + "content": "Copyright and related rights waived via CC0. ", + "url": "https://specs.status.im/spec/6#copyright", + "relUrl": "/spec/6#copyright" },"154": { "doc": "7/GROUP-CHAT", "title": "7/GROUP-CHAT", @@ -962,68 +962,68 @@ "doc": "8/EIPS", "title": "8/EIPS", "content": "Version: 0.2 . Status: Stable . Authors: Ricardo Guilherme Schmidt ricardo3@status.im . ", - "url": "https://specs.status.im/stable/8", - "relUrl": "/stable/8" + "url": "https://specs.status.im/spec/8", + "relUrl": "/spec/8" },"161": { "doc": "8/EIPS", "title": "Abstract", "content": "This specification describes how Status relates with EIPs. ", - "url": "https://specs.status.im/stable/8#abstract", - "relUrl": "/stable/8#abstract" + "url": "https://specs.status.im/spec/8#abstract", + "relUrl": "/spec/8#abstract" },"162": { "doc": "8/EIPS", "title": "Table of Contents", "content": ". | Abstract | Table of Contents | Introduction | Components | . ", - "url": "https://specs.status.im/stable/8#table-of-contents", - "relUrl": "/stable/8#table-of-contents" + "url": "https://specs.status.im/spec/8#table-of-contents", + "relUrl": "/spec/8#table-of-contents" },"163": { "doc": "8/EIPS", "title": "Introduction", "content": "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 . |   | Status v0 | Status v1 | Other | State | . | BIP32 | N | Y | N | stable | . | BIP39 | Y | Y | Y | stable | . | BIP43 | N | Y | N | stable | . | BIP44 | N | Y | N | stable | . | EIP20 | Y | Y | Y | stable | . | EIP55 | Y | Y | Y | stable | . | EIP67 | P | P | N | stable | . | EIP137 | P | P | N | stable | . | EIP155 | Y | Y | Y | stable | . | EIP165 | P | N | N | stable | . | EIP181 | P | N | N | stable | . | EIP191 | Y? | N | Y | stable | . | EIP627 | Y | Y | N | stable | . | EIP681 | Y | N | Y | stable | . | EIP712 | P | P | Y | stable | . | EIP721 | P | P | Y | stable | . | EIP831 | N | Y | N | stable | . | EIP945 | Y | Y | N | stable | . | EIP1102 | Y | Y | Y | stable | . | EIP1193 | Y | Y | Y | stable | . | EIP1577 | Y | P | N | stable | . | EIP1581 | N | Y | N | stable | . | EIP1459 | N |   | N | raw | . ", - "url": "https://specs.status.im/stable/8#introduction", - "relUrl": "/stable/8#introduction" + "url": "https://specs.status.im/spec/8#introduction", + "relUrl": "/spec/8#introduction" },"164": { "doc": "8/EIPS", "title": "Components", "content": "BIP32 - Hierarchical Deterministic Wallets . Support: Dependency. Reference: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki Description: Enable wallets to derive multiple private keys from the same seed. Used for: Dependency of BIP39 and BIP43. BIP39 - Mnemonic code for generating deterministic keys . Support: Dependency. Reference: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki Description: Enable wallet to create private key based on a safe seed phrase. Used for: Security and user experience. BIP43 - Purpose Field for Deterministic Wallets . Support: Dependency. Reference: https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki Description: Enable wallet to create private keys branched for a specific purpose. Used for: Dependency of BIP44, uses “ethereum” coin. BIP44 - Multi-Account Hierarchy for Deterministic Wallets . Support: Dependency. Reference: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki Description: Enable wallet to derive multiple accounts in top of BIP39. Used for: Privacy. Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/constants.cljs#L240 Observation: BIP44 don’t solve privacy issues regarding the transparency of transactions, therefore directly connected addresses through a transactions can be identifiable by a “network reconnaissance attack” over transaction history, this attack together with leakage of information from centralized services, such as exchanges, would be fatal against the whole privacy of users, regardless of BIP44. EIP20 - Fungible Token . Support: Full. Reference: https://eips.ethereum.org/EIPS/eip-20 Description: Enable wallets to use tokens based on smart contracts compliant with this standard. Used for: Wallet feature. Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs . EIP55 - Mixed-case checksum address encoding . Support: Full. Reference: https://eips.ethereum.org/EIPS/eip-55 Description: Checksum standard that uses lowercase and uppercase inside address hex value. Used for: Sanity check of forms using ethereum address. Related: https://github.com/status-im/status-react/issues/4959 https://github.com/status-im/status-react/issues/8707 Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip55.cljs . EIP67 - Standard URI scheme with metadata, value and byte code . Support: Partial. Reference: https://github.com/ethereum/EIPs/issues/67 Description: A standard way of creating Ethereum URIs for various use-cases. Used for: Legacy support. https://github.com/status-im/status-react/issues/875 . EIP137 - Ethereum Domain Name Service - Specification . Support: Partial. Reference: https://eips.ethereum.org/EIPS/eip-137 Description: Enable wallets to lookup ENS names. Used for: User experience, as a wallet and identity feature, usernames. Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/ens.cljs#L86 . EIP155 - Simple replay attack protection . Support: Full. Reference: https://eips.ethereum.org/EIPS/eip-155 Description: Defined chainId parameter in the singed ethereum transaction payload. Used for: Signing transactions, crucial to safety of users against replay attacks. Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/core.cljs . EIP165 - Standard Interface Detection . Support: Dependency/Partial. Reference: https://eips.ethereum.org/EIPS/eip-165 Description: Standard interface for contract to answer if it supports other interfaces. Used for: Dependency of ENS and EIP721. Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip165.cljs . EIP181 - ENS support for reverse resolution of Ethereum addresses . Support: Partial. Reference: https://eips.ethereum.org/EIPS/eip-181 Description: Enable wallets to render reverse resolution of Ethereum addresses. Used for: Wallet feature. Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/ens.cljs#L86 . EIP191 - Signed Message . Support: Full. Reference: https://eips.ethereum.org/EIPS/eip-191 Description: Contract signature standard, adds an obligatory padding to signed message to differentiate from Ethereum Transaction messages. Used for: Dapp support, security, dependency of ERC712. EIP627 - Whisper Specification . Support: Full. Reference: https://eips.ethereum.org/EIPS/eip-627 Description: format of Whisper messages within the ÐΞVp2p Wire Protocol. Used for: Chat protocol. EIP681 - URL Format for Transaction Requests . Support: Partial. Reference: https://eips.ethereum.org/EIPS/eip-681 Description: A link that pop up a transaction in the wallet. Used for: Useful as QR code data for transaction requests, chat transaction requests and for dapp links to transaction requests. Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip681.cljs Related: Issue #9183: URL Format for Transaction Requests (EIP681) is poorly supported https://github.com/status-im/status-react/pull/9240 https://github.com/status-im/status-react/issues/9238 https://github.com/status-im/status-react/issues/7214 https://github.com/status-im/status-react/issues/7325 https://github.com/status-im/status-react/issues/8150 . EIP712 - Typed Signed Message . Support: Partial. Reference: https://eips.ethereum.org/EIPS/eip-712 Description: Standardize types for contract signature, allowing users to easily inspect whats being signed. Used for: User experience, security. Related: https://github.com/status-im/status-react/issues/5461 https://github.com/status-im/status-react/commit/ba37f7b8d029d3358c7b284f6a2383b9ef9526c9 . EIP721 - Non Fungible Token . Support: Partial. Reference: https://eips.ethereum.org/EIPS/eip-721 Description: Enable wallets to use tokens based on smart contracts compliant with this standard. Used for: Wallet feature. Related: https://github.com/status-im/status-react/issues/8909 Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/erc721.cljs https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs . EIP945 - Web 3 QR Code Scanning API . Support: Full. Reference: https://github.com/ethereum/EIPs/issues/945 Used for: Sharing contactcode, reading transaction requests. Related: https://github.com/status-im/status-react/issues/5870 . EIP1102 - Opt-in account exposure . Support: Full. Reference: https://eips.ethereum.org/EIPS/eip-1102 Description: Allow users to opt-in the exposure of their ethereum address to dapps they browse. Used for: Privacy, DApp support. Related: https://github.com/status-im/status-react/issues/7985 . EIP1193 - Ethereum Provider JavaScript API . Support: Full. Reference: https://eips.ethereum.org/EIPS/eip-1193 Description: Allows dapps to recognize event changes on wallet. Used for: DApp support. Related: https://github.com/status-im/status-react/pull/7246 . EIP1577 - contenthash field for ENS . Support: Partial. Reference: https://eips.ethereum.org/EIPS/eip-1577 Description: Allows users browse ENS domains using contenthash standard. Used for: Browser, DApp support. Related: https://github.com/status-im/status-react/issues/6688 Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/utils/contenthash.cljs https://github.com/status-im/status-react/blob/develop/test/cljs/status_im/test/utils/contenthash.cljs#L5 . EIP1581 - Non-wallet usage of keys derived from BIP-32 trees . Support: Partial. Reference: https://eips.ethereum.org/EIPS/eip-1581 Description: Allow wallet to derive keys that are less sensible (non wallet). Used for: Security (don’t reuse wallet key) and user experience (don’t request keycard every login). Related: https://github.com/status-im/status-react/issues/9088 https://github.com/status-im/status-react/pull/9096 Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/constants.cljs#L242 . EIP1459 - Node Discovery via DNS . Support: - Reference: https://eips.ethereum.org/EIPS/eip-1459 Description: Allows the storing and retrieving of nodes through merkle trees stored in TXT records of a domain. Used for: Finding Waku nodes. Related: - Sourcecode: - . ", - "url": "https://specs.status.im/stable/8#components", - "relUrl": "/stable/8#components" + "url": "https://specs.status.im/spec/8#components", + "relUrl": "/spec/8#components" },"165": { "doc": "8/EIPS", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/8#copyright", - "relUrl": "/stable/8#copyright" + "url": "https://specs.status.im/spec/8#copyright", + "relUrl": "/spec/8#copyright" },"166": { "doc": "9/ETHEREUM-USAGE", "title": "9/ETHEREUM-USAGE", "content": "Version: 0.1 . Status: Stable . Authors: Andrea Maria Piana andreap@status.im . ", - "url": "https://specs.status.im/stable/9", - "relUrl": "/stable/9" + "url": "https://specs.status.im/spec/9", + "relUrl": "/spec/9" },"167": { "doc": "9/ETHEREUM-USAGE", "title": "Status interactions with the Ethereum blockchain", "content": "This specification documents all the interactions that the Status client has with the Ethereum blockchain. All the interactions are made through JSON-RPC. Currently Infura is used. The client assumes high-availability, otherwise it will not be able to interact with the Ethereum blockchain. Status nodes rely on these Infura nodes to validate the integrity of the transaction and report a consistent history. Key handling is described here . | Wallet | ENS | . ", - "url": "https://specs.status.im/stable/9#status-interactions-with-the-ethereum-blockchain", - "relUrl": "/stable/9#status-interactions-with-the-ethereum-blockchain" + "url": "https://specs.status.im/spec/9#status-interactions-with-the-ethereum-blockchain", + "relUrl": "/spec/9#status-interactions-with-the-ethereum-blockchain" },"168": { "doc": "9/ETHEREUM-USAGE", "title": "Wallet", "content": "The wallet in Status has two main components: . 1) Sending transactions 2) Fetching balance . In the section below are described the RPC calls made the nodes, with a brief description of their functionality and how it is used by Status. | Sending transactions . | EstimateGas | PendingNonceAt | SuggestGasPrice | SendTransaction | . | Fetching balance . | BlockByHash | BlockByNumber | FilterLogs | HeaderByNumber | NonceAt | TransactionByHash | TransactionReceipt | . | . Sending transactions . EstimateGas . EstimateGas tries to estimate the gas needed to execute a specific transaction based on the current pending state of the backend blockchain. There is no guarantee that this is the true gas limit requirement as other transactions may be added or removed by miners, but it should provide a basis for setting a reasonable default. func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L499 . PendingNonceAt . PendingNonceAt returns the account nonce of the given account in the pending state. This is the nonce that should be used for the next transaction. func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L440 . SuggestGasPrice . SuggestGasPrice retrieves the currently suggested gas price to allow a timely execution of a transaction. func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L487 . SendTransaction . SendTransaction injects a signed transaction into the pending pool for execution. If the transaction was a contract creation use the TransactionReceipt method to get the contract address after the transaction has been mined. func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L512 . Fetching balance . 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 are also fetched if enabled. A Status node supports by default the following tokens. Custom tokens can be added by specifying the address, symbol and decimals. BlockByHash . BlockByHash returns the given full block. It is used by status to fetch a given block which will then be inspected for transfers to the user address, both tokens and ETH. func (ec *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L78 . BlockByNumber . BlockByNumber returns a block from the current canonical chain. If number is nil, the latest known block is returned. func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L82 . FilterLogs . FilterLogs executes a filter query. Status uses this function to filter out logs, using the hash of the block and the address of interest, both inbound and outbound. func (ec *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L377 . NonceAt . NonceAt returns the account nonce of the given account. func (ec *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L366 . TransactionByHash . TransactionByHash returns the transaction with the given hash, used to inspect those transactions made/received by the user. func (ec *Client) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L202 . HeaderByNumber . HeaderByNumber returns a block header from the current canonical chain. func (ec *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L172 . TransactionReceipt . TransactionReceipt returns the receipt of a transaction by transaction hash. It is used in status to check if a token transfer was made to the user address. func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) . https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L270 . ", - "url": "https://specs.status.im/stable/9#wallet", - "relUrl": "/stable/9#wallet" + "url": "https://specs.status.im/spec/9#wallet", + "relUrl": "/spec/9#wallet" },"169": { "doc": "9/ETHEREUM-USAGE", "title": "ENS", "content": "All the interactions with ENS are made through the ENS contract . For the stateofus.eth username, one can be registered through these contracts . Registering, releasing and updating . | Registering a username | Releasing a username | Updating a username | . Slashing . Usernames MUST be in a specific format, otherwise they MAY be slashed: . | They MUST only contain alphanumeric characters | They MUST NOT be in the form 0x[0-9a-f]{5}.* and have more than 12 characters | They MUST NOT be in the reserved list | They MUST NOT be too short, this is dynamically set in the contract and can be checked against the contract . | Slash a reserved username | Slash an invalid username | Slash a username too similar to an address | Slash a username that is too short | . ENS names are propagated through ChatMessage and ContactUpdate payload. A client SHOULD verify ens names against the public key of the sender on receiving the message against the ENS contract . ", - "url": "https://specs.status.im/stable/9#ens", - "relUrl": "/stable/9#ens" + "url": "https://specs.status.im/spec/9#ens", + "relUrl": "/spec/9#ens" },"170": { "doc": "9/ETHEREUM-USAGE", "title": "Copyright", "content": "Copyright and related rights waived via CC0. ", - "url": "https://specs.status.im/stable/9#copyright", - "relUrl": "/stable/9#copyright" + "url": "https://specs.status.im/spec/9#copyright", + "relUrl": "/spec/9#copyright" },"171": { "doc": "DEVELOPMENT", "title": "Description", @@ -1208,7 +1208,7 @@ "doc": "Stable specs", "title": "Stable specs", "content": " ", - "url": "https://specs.status.im/stable/", - "relUrl": "/stable/" + "url": "https://specs.status.im/spec/", + "relUrl": "/spec/" } } diff --git a/development.html b/development.html index 6b961b0..fd8548b 100644 --- a/development.html +++ b/development.html @@ -1,4 +1,4 @@ - DEVELOPMENT - Status Specification DEVELOPMENT | Status Specification Link Search Menu Expand Document

Description

This file explains the process of local development for this repository.

Dependencies

This repository is built using Jekyll along with some plugins and a theme.

To install the necessary dependencies on Ubuntu use:

sudo apt-get install ruby-full build-essential zlib1g-dev
+     DEVELOPMENT - Status Specification       DEVELOPMENT | Status Specification               Link      Search      Menu      Expand      Document       

Description

This file explains the process of local development for this repository.

Dependencies

This repository is built using Jekyll along with some plugins and a theme.

To install the necessary dependencies on Ubuntu use:

sudo apt-get install ruby-full build-essential zlib1g-dev
 gem install jekyll bundler
 

It might be necessary to specify installation destination for your Gems:

export GEM_HOME="$HOME/.gems"
 export PATH="$HOME/gems/bin:$PATH"
diff --git a/draft/12.html b/draft/12.html
index 637828a..bae224d 100644
--- a/draft/12.html
+++ b/draft/12.html
@@ -1,4 +1,4 @@
-     12/IPFS gateway for Sticker Pack - Status Specification       12/IPFS gateway for Sticker Pack | Status Specification               Link      Search      Menu      Expand      Document       

12/IPFS gateway for Sticker Pack

Version: 0.1.0

Status: Draft

Authors: Gheorghe Pinzaru gheorghe@status.im

Table of Contents

  1. Abstract
  2. Specification
  3. Copyright

Abstract

This specification describes how Status uses the IPFS gateway to store stickers. The specification explores image format, how a user uploads stickers and how an end user can see them inside the Status app.

Definition

Term Description
Stickers A set of images which can be used to express emotions
Sticker Pack ERC721 token which includes the set of stickers
IPFS P2P network used to store and share data, in this case, the images for the stickerpack

Specification

Image format

Accepted image file types are PNG, JPG/JPEG and GIF, with a maximum allowed size of 300kb. The minimum sticker image resolution is 512x512, and its background SHOULD be transparent.

Distribution

The node implements sticker packs as ERC721 token and contain a set of stickers. The node stores these stickers inside the sticker pack as a set of hyperlinks pointing to IPFS storage. These hyperlinks are publicly available and can be accessed by any user inside the status chat. Stickers can be sent in chat only by accounts that own the sticker pack.

IPFS gateway

At the moment of writing, the current main Status app uses the Infura gateway. However, clients could choose a different gateway or to run own IPFS node. Infura gateway is an HTTPS gateway, which based on an HTTP GET request with the multihash block will return the stored content at that block address.

The node requires the use of a gateway to enable easy access to the resources over HTTP. The node stores each image of a sticker inside IPFS using a unique address that is derived from the hash of the file. This ensures that a file can’t be overridden, and an end-user of the IPFS will receive the same file at a given address.

Security

The IPFS gateway acts as an end-user of the IPFS and allows users of the gateway to access IPFS without connection to the P2P network. Usage of a gateway introduces potential risk for the users of that gateway provider. In case of a compromise in the security of the provider, meta information such as IP address, User-Agent and other of its users can be leaked. If the provider servers are unavailable the node loses access through the gateway to the IPFS network.

Status sticker usage

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 be available for installation a Sticker Pack should be submitted to Sticker market by an author.

Submit a sticker

To submit a sticker pack, the author should upload all assets to IPFS. Then generate a payload including name, author, thumbnail, preview and a list of stickers in the EDN format. Following this structure:

{meta {:name "Sticker pack name"
+     12/IPFS gateway for Sticker Pack - Status Specification       12/IPFS gateway for Sticker Pack | Status Specification               Link      Search      Menu      Expand      Document       

12/IPFS gateway for Sticker Pack

Version: 0.1.0

Status: Draft

Authors: Gheorghe Pinzaru gheorghe@status.im

Table of Contents

  1. Abstract
  2. Specification
  3. Copyright

Abstract

This specification describes how Status uses the IPFS gateway to store stickers. The specification explores image format, how a user uploads stickers and how an end user can see them inside the Status app.

Definition

Term Description
Stickers A set of images which can be used to express emotions
Sticker Pack ERC721 token which includes the set of stickers
IPFS P2P network used to store and share data, in this case, the images for the stickerpack

Specification

Image format

Accepted image file types are PNG, JPG/JPEG and GIF, with a maximum allowed size of 300kb. The minimum sticker image resolution is 512x512, and its background SHOULD be transparent.

Distribution

The node implements sticker packs as ERC721 token and contain a set of stickers. The node stores these stickers inside the sticker pack as a set of hyperlinks pointing to IPFS storage. These hyperlinks are publicly available and can be accessed by any user inside the status chat. Stickers can be sent in chat only by accounts that own the sticker pack.

IPFS gateway

At the moment of writing, the current main Status app uses the Infura gateway. However, clients could choose a different gateway or to run own IPFS node. Infura gateway is an HTTPS gateway, which based on an HTTP GET request with the multihash block will return the stored content at that block address.

The node requires the use of a gateway to enable easy access to the resources over HTTP. The node stores each image of a sticker inside IPFS using a unique address that is derived from the hash of the file. This ensures that a file can’t be overridden, and an end-user of the IPFS will receive the same file at a given address.

Security

The IPFS gateway acts as an end-user of the IPFS and allows users of the gateway to access IPFS without connection to the P2P network. Usage of a gateway introduces potential risk for the users of that gateway provider. In case of a compromise in the security of the provider, meta information such as IP address, User-Agent and other of its users can be leaked. If the provider servers are unavailable the node loses access through the gateway to the IPFS network.

Status sticker usage

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 be available for installation a Sticker Pack should be submitted to Sticker market by an author.

Submit a sticker

To submit a sticker pack, the author should upload all assets to IPFS. Then generate a payload including name, author, thumbnail, preview and a list of stickers in the EDN format. Following this structure:

{meta {:name "Sticker pack name"
        :author "Author Name"
        :thumbnail "e30101701220602163b4f56c747333f43775fdcbe4e62d6a3e147b22aaf6097ce0143a6b2373"
        :preview "e30101701220ef54a5354b78ef82e542bd468f58804de71c8ec268da7968a1422909357f2456"
diff --git a/draft/13.html b/draft/13.html
index 35e2c41..bb84402 100644
--- a/draft/13.html
+++ b/draft/13.html
@@ -1 +1 @@
-     13/3RD-PARTY-USAGE - Status Specification       13/3RD-PARTY-USAGE | Status Specification               Link      Search      Menu      Expand      Document       

13/3RD-PARTY

Version: 0.1

Status: Draft

Authors: Volodymyr Kozieiev volodymyr@status.im

Third party APIs used for core functionality

Table of Contents

  1. Abstract
  2. Definitions
  3. Why 3rd party API can be a problem?
  4. 3rd party APIs used by Status
  5. Changelog
  6. Copyright

Abstract

This specification discusses 3rd party APIs that Status relies on. These APIs provide various capabilities such as:

  • communicate with the Ethereum network
  • allow users to see address and transaction details on external website
  • get fiat/crypto exchange rates
  • get information about collectibles
  • hosts privacy policy

Definitions

Term Description
Fiat money Currency which established as money, often by government regulation, but that has no intrinsic value
Full node Any computer, connected to the Ethereum network, which fully enforces all the consensus rules of Ethereum.
Crypto-collectible A cryptographically unique, non-fungible digital asset . Unlike cryptocurrencies, which require all tokens to be identical, each crypto-collectible token is unique or limited in quantity.

Why 3rd party API can be a problem?

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

Infura

What is it?

Infura hosts a collection of full nodes for the Ethereum network and provides an API to access both the Ethereum and IPFS networks without having to run a full node.

How Status use it?

Status works on mobile devices and therefore can’t rely on local node. So all communication to Ethereum network happens via Infura.

Concerns

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.

Etherscan

What is it?

Etherscan is a service that allows user to explore and search the Ethereum blockchain for transactions, addresses, tokens, prices and other activities taking place on Ethereum.

How Status use it?

Status Wallet allows users to view details of addresses and transactions on Etherscan.

Concerns

If Etherscan fails user won’t be able to view address or transaction details with it. But inside the app this info will still be available.

CryptoCompare

What is it?

CryptoCompare is a service that shows live streaming prices, charts and analysis from top crypto exchanges.

How Status use it?

Status regularly fetches crypto prices from CryptoCompare. Using that info Status calculates fiat value for transaction or wallet assets.

Concerns

Making a HTTP request means that a user leaks metadata, which can be used in various attacks if an attacker hacks the service. If CryptoCompare fails Status won’t be able to show fiat equivalent of crypto in wallet.

Collectibles

There is a set of services that used for getting information about collectibles:

  • https://api.pixura.io/graphql
  • https://www.etheremon.com/api
  • https://us-central1-cryptostrikers-prod.cloudfunctions.net/cards/
  • https://api.cryptokitties.co/
Concerns

Making a HTTP request means that a user leaks metadata, which can be used in various attacks if an attacker hacks the service.

Iubenda

What is it?

Service that helps in creating documents that make websites and apps compliant with the law across multiple countries and legislations.

How Status use it?

Privacy policy of Status hosted on Iubenda.

Concerns

If Iubenda fails Status users won’t be able to navigate to app’s privacy policy.

Changelog

Version Comment
0.1.0 Initial Release

Copyright and related rights waived via CC0.

+ 13/3RD-PARTY-USAGE - Status Specification 13/3RD-PARTY-USAGE | Status Specification Link Search Menu Expand Document

13/3RD-PARTY

Version: 0.1

Status: Draft

Authors: Volodymyr Kozieiev volodymyr@status.im

Third party APIs used for core functionality

Table of Contents

  1. Abstract
  2. Definitions
  3. Why 3rd party API can be a problem?
  4. 3rd party APIs used by Status
  5. Changelog
  6. Copyright

Abstract

This specification discusses 3rd party APIs that Status relies on. These APIs provide various capabilities such as:

  • communicate with the Ethereum network
  • allow users to see address and transaction details on external website
  • get fiat/crypto exchange rates
  • get information about collectibles
  • hosts privacy policy

Definitions

Term Description
Fiat money Currency which established as money, often by government regulation, but that has no intrinsic value
Full node Any computer, connected to the Ethereum network, which fully enforces all the consensus rules of Ethereum.
Crypto-collectible A cryptographically unique, non-fungible digital asset . Unlike cryptocurrencies, which require all tokens to be identical, each crypto-collectible token is unique or limited in quantity.

Why 3rd party API can be a problem?

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

Infura

What is it?

Infura hosts a collection of full nodes for the Ethereum network and provides an API to access both the Ethereum and IPFS networks without having to run a full node.

How Status use it?

Status works on mobile devices and therefore can’t rely on local node. So all communication to Ethereum network happens via Infura.

Concerns

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.

Etherscan

What is it?

Etherscan is a service that allows user to explore and search the Ethereum blockchain for transactions, addresses, tokens, prices and other activities taking place on Ethereum.

How Status use it?

Status Wallet allows users to view details of addresses and transactions on Etherscan.

Concerns

If Etherscan fails user won’t be able to view address or transaction details with it. But inside the app this info will still be available.

CryptoCompare

What is it?

CryptoCompare is a service that shows live streaming prices, charts and analysis from top crypto exchanges.

How Status use it?

Status regularly fetches crypto prices from CryptoCompare. Using that info Status calculates fiat value for transaction or wallet assets.

Concerns

Making a HTTP request means that a user leaks metadata, which can be used in various attacks if an attacker hacks the service. If CryptoCompare fails Status won’t be able to show fiat equivalent of crypto in wallet.

Collectibles

There is a set of services that used for getting information about collectibles:

  • https://api.pixura.io/graphql
  • https://www.etheremon.com/api
  • https://us-central1-cryptostrikers-prod.cloudfunctions.net/cards/
  • https://api.cryptokitties.co/
Concerns

Making a HTTP request means that a user leaks metadata, which can be used in various attacks if an attacker hacks the service.

Iubenda

What is it?

Service that helps in creating documents that make websites and apps compliant with the law across multiple countries and legislations.

How Status use it?

Privacy policy of Status hosted on Iubenda.

Concerns

If Iubenda fails Status users won’t be able to navigate to app’s privacy policy.

Changelog

Version Comment
0.1.0 Initial Release

Copyright and related rights waived via CC0.

diff --git a/draft/14.html b/draft/14.html index a7c58ff..1e9ad71 100644 --- a/draft/14.html +++ b/draft/14.html @@ -1 +1 @@ - 14/Dapp browser API usage - Status Specification 14/Dapp browser API usage | Status Specification Link Search Menu Expand Document

Dapp browser API usage

Table of Contents

  1. Abstract
  2. Definitions
  3. Overview
  4. Usage
  5. Implementation
  6. Compatibility
  7. Changelog
  8. Copyright

Abstract

This document describes requirements that an application must fulfill in order to provide a proper environment for Dapps running inside a browser. A description of the Status Dapp API is provided, along with an overview of bidirectional communication underlying the API implementation. The document also includes a list of EIPs that this API implements.

Definitions

Term Description
Webview Platform-specific browser core implementation.
Ethereum Provider A JS object (window.ethereum) injected into each web page opened in the browser providing web3 compatible provider.
Bridge A set of facilities allow bidirectional communication between JS code and the application.

Overview

The application should expose an Ethereum Provider object (window.ethereum) to JS code running inside the browser. It is important to have the window.ethereum object available before the page loads, otherwise Dapps might not work correctly.

Additionally, the browser component should also provide bidirectional communication between JS code and the application.

Usage in Dapps

Dapps can use the below properties and methods of window.ethereum object.

Properties

isStatus

Returns true. Can be used by the Dapp to find out whether it’s running inside Status.

status

Returns a StatusAPI object. For now it supports one method: getContactCode that sends a contact-code request to Status.

Methods

isConnected

Similarly to Ethereum JS API docs, it should be called to check if connection to a node exists. On Status, this fn always returns true, as once Status is up and running, node is automatically started.

scanQRCode

Sends a qr-code Status API request.

request

request method as defined by EIP-1193.

Unused

Below are some legacy methods that some Dapps might still use.

enable (DEPRECATED)

Sends a web3 Status API request. It returns a first entry in the list of available accounts.

Legacy enable method as defined by EIP1102.

send (DEPRECATED)

Legacy send method as defined by EIP1193.

sendAsync (DEPRECATED)

Legacy sendAsync method as defined by EIP1193.

sendSync (DEPRECATED)

Legacy send method.

Implementation

Status uses a forked version of react-native-webview to display web or dapps content. The fork provides an Android implementation of JS injection before page load. It is required in order to properly inject Ethereum Provider object.

Status injects two JS scripts:

Dapps running inside a browser communicate with Status Ethereum node by means of a bridge provided by react-native-webview library. The bridge allows for bidirectional communication between browser and Status. In order to do so, it injects a special ReactNativeWebview object into each page it loads.

On Status (React Native) end, react-native-webview library provides WebView.injectJavascript function on a webview component that allows to execute arbitrary code inside the webview. Thus it is possible to inject a function call passing Status node response back to the Dapp.

Below is the table briefly describing what functions/properties are used. More details available in package docs.

Direction Side Method
Browser->Status JS ReactNativeWebView.postMessage()
Browser->Status RN WebView.onMessage()
Status->Browser JS ReactNativeWebView.onMessage()
Status->Browser RN WebView.injectJavascript()

Compatibility

Status browser supports the following EIPs:

  • EIP1102: eth_requestAccounts support
  • EIP1193: connect, disconnect, chainChanged, and accountsChanged event support is not implemented

Changelog

Version Comment
0.1.0 Initial Release

Copyright and related rights waived via CC0.

+ 14/Dapp browser API usage - Status Specification 14/Dapp browser API usage | Status Specification Link Search Menu Expand Document

Dapp browser API usage

Table of Contents

  1. Abstract
  2. Definitions
  3. Overview
  4. Usage
  5. Implementation
  6. Compatibility
  7. Changelog
  8. Copyright

Abstract

This document describes requirements that an application must fulfill in order to provide a proper environment for Dapps running inside a browser. A description of the Status Dapp API is provided, along with an overview of bidirectional communication underlying the API implementation. The document also includes a list of EIPs that this API implements.

Definitions

Term Description
Webview Platform-specific browser core implementation.
Ethereum Provider A JS object (window.ethereum) injected into each web page opened in the browser providing web3 compatible provider.
Bridge A set of facilities allow bidirectional communication between JS code and the application.

Overview

The application should expose an Ethereum Provider object (window.ethereum) to JS code running inside the browser. It is important to have the window.ethereum object available before the page loads, otherwise Dapps might not work correctly.

Additionally, the browser component should also provide bidirectional communication between JS code and the application.

Usage in Dapps

Dapps can use the below properties and methods of window.ethereum object.

Properties

isStatus

Returns true. Can be used by the Dapp to find out whether it’s running inside Status.

status

Returns a StatusAPI object. For now it supports one method: getContactCode that sends a contact-code request to Status.

Methods

isConnected

Similarly to Ethereum JS API docs, it should be called to check if connection to a node exists. On Status, this fn always returns true, as once Status is up and running, node is automatically started.

scanQRCode

Sends a qr-code Status API request.

request

request method as defined by EIP-1193.

Unused

Below are some legacy methods that some Dapps might still use.

enable (DEPRECATED)

Sends a web3 Status API request. It returns a first entry in the list of available accounts.

Legacy enable method as defined by EIP1102.

send (DEPRECATED)

Legacy send method as defined by EIP1193.

sendAsync (DEPRECATED)

Legacy sendAsync method as defined by EIP1193.

sendSync (DEPRECATED)

Legacy send method.

Implementation

Status uses a forked version of react-native-webview to display web or dapps content. The fork provides an Android implementation of JS injection before page load. It is required in order to properly inject Ethereum Provider object.

Status injects two JS scripts:

Dapps running inside a browser communicate with Status Ethereum node by means of a bridge provided by react-native-webview library. The bridge allows for bidirectional communication between browser and Status. In order to do so, it injects a special ReactNativeWebview object into each page it loads.

On Status (React Native) end, react-native-webview library provides WebView.injectJavascript function on a webview component that allows to execute arbitrary code inside the webview. Thus it is possible to inject a function call passing Status node response back to the Dapp.

Below is the table briefly describing what functions/properties are used. More details available in package docs.

Direction Side Method
Browser->Status JS ReactNativeWebView.postMessage()
Browser->Status RN WebView.onMessage()
Status->Browser JS ReactNativeWebView.onMessage()
Status->Browser RN WebView.injectJavascript()

Compatibility

Status browser supports the following EIPs:

  • EIP1102: eth_requestAccounts support
  • EIP1193: connect, disconnect, chainChanged, and accountsChanged event support is not implemented

Changelog

Version Comment
0.1.0 Initial Release

Copyright and related rights waived via CC0.

diff --git a/draft/16.html b/draft/16.html index 02bf57c..cf50c32 100644 --- a/draft/16.html +++ b/draft/16.html @@ -1,4 +1,4 @@ - 16/Keycard Usage for Wallet and Chat Keys - Status Specification 16/Keycard Usage for Wallet and Chat Keys | Status Specification Link Search Menu Expand Document

Table of Contents

  1. Abstract
  2. Definitions
  3. Multiaccount creation
  4. Multiaccount restoring via pairing
  5. Multiaccount unlocking
  6. Transaction signing
  7. Account derivation
  8. Reset pin
  9. Unblock pin
  10. Status go calls
  11. Where are the keys stored?
  12. Copyright

Abstract

In this specification, we describe how Status communicates with Keycard to create, store and use multiaccount.

Definitions

Term Description
Keycard Hardwallet https://keycard.tech/docs/
   

Multiaccount creation/restoring

Creation and restoring via mnemonic

  1. status-im.hardwallet.card/get-application-info request: nil response: {"initialized?" false}
  2. status-im.hardwallet.card/init-card request: {:pin 123123} response:
    {"password" "nEJXqf6VWbqeC5oN", 
    +     16/Keycard Usage for Wallet and Chat Keys - Status Specification       16/Keycard Usage for Wallet and Chat Keys | Status Specification               Link      Search      Menu      Expand      Document       

    Table of Contents

    1. Abstract
    2. Definitions
    3. Multiaccount creation
    4. Multiaccount restoring via pairing
    5. Multiaccount unlocking
    6. Transaction signing
    7. Account derivation
    8. Reset pin
    9. Unblock pin
    10. Status go calls
    11. Where are the keys stored?
    12. Copyright

    Abstract

    In this specification, we describe how Status communicates with Keycard to create, store and use multiaccount.

    Definitions

    Term Description
    Keycard Hardwallet https://keycard.tech/docs/
       

    Multiaccount creation/restoring

    Creation and restoring via mnemonic

    1. status-im.hardwallet.card/get-application-info request: nil response: {"initialized?" false}
    2. status-im.hardwallet.card/init-card request: {:pin 123123} response:
      {"password" "nEJXqf6VWbqeC5oN", 
        "puk" "411810112887", 
        "pin" "123123"}
       
    3. status-im.hardwallet.card/get-application-info request: nil response:
       {"free-pairing-slots" 5, 
      diff --git a/draft/3.html b/draft/3.html
      index 1de5efd..93f5a6c 100644
      --- a/draft/3.html
      +++ b/draft/3.html
      @@ -1,4 +1,4 @@
      -     3/WHISPER-USAGE - Status Specification       3/WHISPER-USAGE | Status Specification               Link      Search      Menu      Expand      Document       

      3/WHISPER-USAGE

      Version: 0.3

      Status: Draft

      Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im (alphabetical order)

      Abstract

      Status uses Whisper to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. This allows anyone to listen on a single channel.

      Additionally, since anyone can receive Whisper envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper.

      Finally, using an extension of Whisper provides the ability to do offline messaging.

      Reason

      Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat.

      Terminology

      • Whisper node: an Ethereum node with Whisper V6 enabled (in the case of geth, it’s --shh option)
      • Whisper network: a group of Whisper nodes connected together through the internet connection and forming a graph
      • Message: a decrypted Whisper message
      • Offline message: an archived envelope
      • Envelope: an encrypted message with metadata like topic and Time-To-Live

      Whisper packets

      Packet Name Code EIP-627 References
      Status 0 Handshake
      Messages 1 EIP-627
      PoW Requirement 2 EIP-627
      Bloom Filter 3 EIP-627
      Batch Ack 11 𝘅 Undocumented
      Message Response 12 𝘅 Undocumented
      P2P Sync Request 123 𝘅 Undocumented
      P2P Sync Response 124 𝘅 Undocumented
      P2P Request Complete 125 𝘅 4/WHISPER-MAILSERVER
      P2P Request 126 4/WHISPER-MAILSERVER
      P2P Messages 127 ✔/𝘅 (EIP-627 supports only single envelope in a packet) 4/WHISPER-MAILSERVER

      Whisper node configuration

      A Whisper node must be properly configured to receive messages from Status clients.

      Whisper’s Proof Of Work algorithm is used to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings:

      • proof-of-work requirement not larger than 0.00001
      • time-to-live not lower than 10 (in seconds)
      • any payload below 50000 bytes MUST be sent with a PoW Target of at least 0.002, in order to maintain backward compatibility with version 0.2 and Status app version 1.3 and below

      Handshake

      Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items:

      [ protocolVersion, PoW, bloom, isLightNode, confirmationsEnabled, rateLimits ]
      +     3/WHISPER-USAGE - Status Specification       3/WHISPER-USAGE | Status Specification               Link      Search      Menu      Expand      Document       

      3/WHISPER-USAGE

      Version: 0.3

      Status: Draft

      Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im (alphabetical order)

      Abstract

      Status uses Whisper to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. This allows anyone to listen on a single channel.

      Additionally, since anyone can receive Whisper envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper.

      Finally, using an extension of Whisper provides the ability to do offline messaging.

      Reason

      Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat.

      Terminology

      • Whisper node: an Ethereum node with Whisper V6 enabled (in the case of geth, it’s --shh option)
      • Whisper network: a group of Whisper nodes connected together through the internet connection and forming a graph
      • Message: a decrypted Whisper message
      • Offline message: an archived envelope
      • Envelope: an encrypted message with metadata like topic and Time-To-Live

      Whisper packets

      Packet Name Code EIP-627 References
      Status 0 Handshake
      Messages 1 EIP-627
      PoW Requirement 2 EIP-627
      Bloom Filter 3 EIP-627
      Batch Ack 11 𝘅 Undocumented
      Message Response 12 𝘅 Undocumented
      P2P Sync Request 123 𝘅 Undocumented
      P2P Sync Response 124 𝘅 Undocumented
      P2P Request Complete 125 𝘅 4/WHISPER-MAILSERVER
      P2P Request 126 4/WHISPER-MAILSERVER
      P2P Messages 127 ✔/𝘅 (EIP-627 supports only single envelope in a packet) 4/WHISPER-MAILSERVER

      Whisper node configuration

      A Whisper node must be properly configured to receive messages from Status clients.

      Whisper’s Proof Of Work algorithm is used to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings:

      • proof-of-work requirement not larger than 0.00001
      • time-to-live not lower than 10 (in seconds)
      • any payload below 50000 bytes MUST be sent with a PoW Target of at least 0.002, in order to maintain backward compatibility with version 0.2 and Status app version 1.3 and below

      Handshake

      Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items:

      [ protocolVersion, PoW, bloom, isLightNode, confirmationsEnabled, rateLimits ]
       

      protocolVersion: version of the Whisper protocol PoW: minimum PoW accepted by the peer bloom: bloom filter of Whisper topic accepted by the peer isLightNode: when true, the peer won’t forward messages confirmationsEnabled: when true, the peer will send message confirmations rateLimits: is [ RateLimitIP, RateLimitPeerID, RateLimitTopic ] where each values is an integer with a number of accepted packets per second per IP, Peer ID, and Topic respectively

      bloom, isLightNode, confirmationsEnabled, and rateLimits are all optional arguments in the handshake. However, if an optional field is specified, all optional fields preceding it MUST also be specified in order to be unambiguous.

      Rate limiting

      In order to provide an optional very basic Denial-of-Service attack protection, each node SHOULD define its own rate limits. The rate limits SHOULD be applied on IPs, peer IDs, and envelope topics.

      Each node MAY decide to whitelist, i.e. do not rate limit, selected IPs or peer IDs.

      If a peer exceeds node’s rate limits, the connection between them MAY be dropped.

      Each node SHOULD broadcast its rate limits to its peers using rate limits packet code (0x14). The rate limits is RLP-encoded information:

      [ IP limits, PeerID limits, Topic limits ]
       

      IP limits: 4-byte wide unsigned integer PeerID limits: 4-byte wide unsigned integer Topic limits: 4-byte wide unsigned integer

      The rate limits MAY also be sent as an optional parameter in the handshake.

      Each node SHOULD respect rate limits advertised by its peers. The number of packets SHOULD be throttled in order not to exceed peer’s rate limits. If the limit gets exceeded, the connection MAY be dropped by the peer.

      Keys management

      The protocol requires a key (symmetric or asymmetric) for the following actions:

      • signing & verifying messages (asymmetric key)
      • encrypting & decrypting messages (asymmetric or symmetric key).

      As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory.

      Keys management for PFS is described in 5/SECURE-TRANSPORT.

      The Status protocols uses a few particular Whisper topics to achieve its goals.

      Contact code topic

      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.

      Contact code topic MUST be created following the algorithm below:

      contactCode := "0x" + hexEncode(activePublicKey) + "-contact-code"
       
      diff --git a/draft/6.html b/draft/6.html
      index d1f5af2..7551e0a 100644
      --- a/draft/6.html
      +++ b/draft/6.html
      @@ -1,4 +1,4 @@
      -     6/PAYLOADS - Status Specification       6/PAYLOADS | Status Specification               Link      Search      Menu      Expand      Document       

      6/PAYLOADS

      Version: 0.5

      Status: Draft

      Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

      Abstract

      This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases.

      The payloads aims to be flexible enough to support messaging but also cases described in the Status Whitepaper as well as various clients created using different technologies.

      Table of Contents

      Introduction

      This document describes the payload format and some special considerations.

      Payload wrapper

      The node wraps all payloads in a protobuf record record:

      message StatusProtocolMessage {
      +     6/PAYLOADS - Status Specification       6/PAYLOADS | Status Specification               Link      Search      Menu      Expand      Document       

      6/PAYLOADS

      Version: 0.5

      Status: Draft

      Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

      Abstract

      This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases.

      The payloads aims to be flexible enough to support messaging but also cases described in the Status Whitepaper as well as various clients created using different technologies.

      Table of Contents

      Introduction

      This document describes the payload format and some special considerations.

      Payload wrapper

      The node wraps all payloads in a protobuf record record:

      message StatusProtocolMessage {
         bytes signature = 4001;
         bytes payload = 4002;
       }
      diff --git a/draft/7.html b/draft/7.html
      index f40f27f..0c0072e 100644
      --- a/draft/7.html
      +++ b/draft/7.html
      @@ -1,4 +1,4 @@
      -     7/GROUP-CHAT - Status Specification       7/GROUP-CHAT | Status Specification               Link      Search      Menu      Expand      Document       

      7/GROUP-CHAT

      Version: 0.1

      Status: Draft

      Authors: Andrea Maria Piana andreap@status.im

      Table of Contents

      Abstract

      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

      The node uses membership updates messages to propagate group chat membership changes. The protobuf format is described in the 6/PAYLOADS. Below describes each specific field.

      The protobuf messages are:

      // MembershipUpdateMessage is a message used to propagate information
      +     7/GROUP-CHAT - Status Specification       7/GROUP-CHAT | Status Specification               Link      Search      Menu      Expand      Document       

      7/GROUP-CHAT

      Version: 0.1

      Status: Draft

      Authors: Andrea Maria Piana andreap@status.im

      Table of Contents

      Abstract

      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

      The node uses membership updates messages to propagate group chat membership changes. The protobuf format is described in the 6/PAYLOADS. Below describes each specific field.

      The protobuf messages are:

      // MembershipUpdateMessage is a message used to propagate information
       // about group membership changes.
       message MembershipUpdateMessage {
         // The chat id of the private group chat
      diff --git a/draft/index.html b/draft/index.html
      index 53bd2df..5fc417d 100644
      --- a/draft/index.html
      +++ b/draft/index.html
      @@ -1 +1 @@
      -     Draft specs - Status Specification       Draft specs | Status Specification               Link      Search      Menu      Expand      Document         
      +     Draft specs - Status Specification       Draft specs | Status Specification               Link      Search      Menu      Expand      Document         
      diff --git a/home.html b/home.html
      index ee86262..8a207fa 100644
      --- a/home.html
      +++ b/home.html
      @@ -1 +1 @@
      -      - Status Specification       Status Specification               Link      Search      Menu      Expand      Document         
      +      - Status Specification       Status Specification               Link      Search      Menu      Expand      Document         
      diff --git a/index.html b/index.html
      index d3c1af3..eaffc39 100644
      --- a/index.html
      +++ b/index.html
      @@ -1 +1 @@
      -      - Status Specification       Status Specification               Link      Search      Menu      Expand      Document       

      Specifications for Status clients

      CI

      This repository contains a list of specifications for implementing Status and its various capabilities.

      How to contribute

      You can read about how to build this project here.

      1. Create an issue for a new Status Improvement Proposal (SIP) or some bug that you’d like to address
      2. Create a corresponding PR and ping some existing SIP editors for review

      If you need help, ask in #protocol at Status / Discord.

      Specification style guidelines

      Become familiar with the specification style guidelines to understand how you should write or amend specifications.

      Spec lifecycle

      Every spec has its own lifecycle that shows its maturity. We indicate this in a similar fashion to COSS Lifecycle:

      At present (March 30, 2020) this means stable specs are what is in v1 of the Status App. Drafts and raw are work in progress specs.

      Status Improvement Proposals (SIPs)

      The main specification for writing a Status client is 1/CLIENT.

      For all full index of all specs, see specs.status.im, especially stable specs.

      Protocol Research

      These are protocols that are currently being researched. These are designed to be useful outside of Status as well. To the extent that these protocols are used within Status clients, they will show up as SIPs in the future.

      To see more on this, please visit the current home: vac protocol.

      Continuous Integration

      The site is built in Our Jenkins CI based off of master branch.

      + - Status Specification Status Specification Link Search Menu Expand Document

      Specifications for Status clients

      CI

      This repository contains a list of specifications for implementing Status and its various capabilities.

      How to contribute

      You can read about how to build this project here.

      1. Create an issue for a new Status Improvement Proposal (SIP) or some bug that you’d like to address
      2. Create a corresponding PR and ping some existing SIP editors for review

      If you need help, ask in #protocol at Status / Discord.

      Specification style guidelines

      Become familiar with the specification style guidelines to understand how you should write or amend specifications.

      Spec lifecycle

      Every spec has its own lifecycle that shows its maturity. We indicate this in a similar fashion to COSS Lifecycle:

      At present (March 30, 2020) this means stable specs are what is in v1 of the Status App. Drafts and raw are work in progress specs.

      Status Improvement Proposals (SIPs)

      The main specification for writing a Status client is 1/CLIENT.

      For all full index of all specs, see specs.status.im, especially stable specs.

      Protocol Research

      These are protocols that are currently being researched. These are designed to be useful outside of Status as well. To the extent that these protocols are used within Status clients, they will show up as SIPs in the future.

      To see more on this, please visit the current home: vac protocol.

      Continuous Integration

      The site is built in Our Jenkins CI based off of master branch.

      diff --git a/post.html b/post.html index 85de6b8..70526dd 100644 --- a/post.html +++ b/post.html @@ -1 +1 @@ - - Status Specification Status Specification Link Search Menu Expand Document
      - Status Specification Status Specification Link Search Menu Expand Document
      + - Status Specification Status Specification Link Search Menu Expand Document
      - Status Specification Status Specification Link Search Menu Expand Document
      diff --git a/raw/16.html b/raw/16.html index 35cf92c..d8f6884 100644 --- a/raw/16.html +++ b/raw/16.html @@ -1,4 +1,4 @@ - 16/PUSH-NOTIFICATION-SERVER - Status Specification 16/PUSH-NOTIFICATION-SERVER | Status Specification Link Search Menu Expand Document

      16/PUSH-NOTIFICATION-SERVER

      Version: 0.1

      Status: Raw

      Authors: Andrea Maria Piana andreap@status.im

      Reason

      Push notifications for iOS devices and some Android devices can only be implemented by relying on APN service for iOS or Firebase.

      This is useful for Android devices that do not support foreground services or that often kill the foreground service.

      iOS only allows certain kind of applications to keep a connection open when in the background, VoIP for example, which current status client does not qualify for.

      Applications on iOS can also request execution time when they are in the background but it has a limited set of use cases, for example it won’t schedule any time if the application was force quit, and generally is not responsive enough to implement a push notification system.

      Therefore Status provides a set of Push notification services that can be used to achieve this functionality.

      Because this can’t be safely implemented in a privacy preserving manner, clients MUST be given an option to opt-in to receiving and sending push notifications. They are disabled by default.

      Requirements

      The party releasing the app MUST possess a certificate for the Apple Push Notification service and its has to run a gorush publicly accessible server for sending the actual notification. The party releasing the app, Status in this case, needs to run its own gorush

      Components

      Gorush instance

      A gorush instance MUST be publicly available, this will be used only by push notification servers.

      Push notification server

      A push notification server used by clients to register for receiving and sending push notifications.

      Registering client

      A Status client that wants to receive push notifications

      Sending client

      A Status client that wants to send push notifications

      Registering with the push notification service

      A client MAY register with one or more Push Notification services of their choice.

      A PNR message (Push Notification Registration) MUST be sent to the partitioned topic for the public key of the node, encrypted with this key.

      The message MUST be wrapped in a ApplicationMetadataMessage with type set to PUSH_NOTIFICATION_REGISTRATION.

      The marshaled protobuf payload MUST also be encrypted with AES-GCM using the Diffie–Hellman key generated from the client and server identity.

      This is done in order to ensure that the extracted key from the signature will be considered invalid if it can’t decrypt the payload.

      The content of the message MUST contain the following protobuf record:

      message PushNotificationRegistration {
      +     16/PUSH-NOTIFICATION-SERVER - Status Specification       16/PUSH-NOTIFICATION-SERVER | Status Specification               Link      Search      Menu      Expand      Document       

      16/PUSH-NOTIFICATION-SERVER

      Version: 0.1

      Status: Raw

      Authors: Andrea Maria Piana andreap@status.im

      Reason

      Push notifications for iOS devices and some Android devices can only be implemented by relying on APN service for iOS or Firebase.

      This is useful for Android devices that do not support foreground services or that often kill the foreground service.

      iOS only allows certain kind of applications to keep a connection open when in the background, VoIP for example, which current status client does not qualify for.

      Applications on iOS can also request execution time when they are in the background but it has a limited set of use cases, for example it won’t schedule any time if the application was force quit, and generally is not responsive enough to implement a push notification system.

      Therefore Status provides a set of Push notification services that can be used to achieve this functionality.

      Because this can’t be safely implemented in a privacy preserving manner, clients MUST be given an option to opt-in to receiving and sending push notifications. They are disabled by default.

      Requirements

      The party releasing the app MUST possess a certificate for the Apple Push Notification service and its has to run a gorush publicly accessible server for sending the actual notification. The party releasing the app, Status in this case, needs to run its own gorush

      Components

      Gorush instance

      A gorush instance MUST be publicly available, this will be used only by push notification servers.

      Push notification server

      A push notification server used by clients to register for receiving and sending push notifications.

      Registering client

      A Status client that wants to receive push notifications

      Sending client

      A Status client that wants to send push notifications

      Registering with the push notification service

      A client MAY register with one or more Push Notification services of their choice.

      A PNR message (Push Notification Registration) MUST be sent to the partitioned topic for the public key of the node, encrypted with this key.

      The message MUST be wrapped in a ApplicationMetadataMessage with type set to PUSH_NOTIFICATION_REGISTRATION.

      The marshaled protobuf payload MUST also be encrypted with AES-GCM using the Diffie–Hellman key generated from the client and server identity.

      This is done in order to ensure that the extracted key from the signature will be considered invalid if it can’t decrypt the payload.

      The content of the message MUST contain the following protobuf record:

      message PushNotificationRegistration {
         enum TokenType {
           UNKNOWN_TOKEN_TYPE = 0;
           APN_TOKEN = 1;
      diff --git a/raw/index.html b/raw/index.html
      index c5290f2..6d10203 100644
      --- a/raw/index.html
      +++ b/raw/index.html
      @@ -1 +1 @@
      -     Raw specs - Status Specification       Raw specs | Status Specification               Link      Search      Menu      Expand      Document       

      Table of contents

      + Raw specs - Status Specification Raw specs | Status Specification Link Search Menu Expand Document

      Table of contents

      diff --git a/sitemap.xml b/sitemap.xml index e65a08f..548c952 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,13 +1,13 @@ -https://specs.status.im/stable/1 +https://specs.status.im/spec/1 -https://specs.status.im/stable/10 +https://specs.status.im/spec/10 -https://specs.status.im/stable/11 +https://specs.status.im/spec/11 https://specs.status.im/draft/12 @@ -19,40 +19,40 @@ https://specs.status.im/draft/14 -https://specs.status.im/stable/15 +https://specs.status.im/spec/15 https://specs.status.im/draft/16 -https://specs.status.im/stable/2 - - -https://specs.status.im/stable/3 +https://specs.status.im/spec/2 https://specs.status.im/draft/3 -https://specs.status.im/stable/4 +https://specs.status.im/spec/3 -https://specs.status.im/stable/5 +https://specs.status.im/spec/4 -https://specs.status.im/stable/6 +https://specs.status.im/spec/5 https://specs.status.im/draft/6 +https://specs.status.im/spec/6 + + https://specs.status.im/draft/7 -https://specs.status.im/stable/8 +https://specs.status.im/spec/8 -https://specs.status.im/stable/9 +https://specs.status.im/spec/9 https://specs.status.im/development @@ -79,7 +79,7 @@ https://specs.status.im/raw/ -https://specs.status.im/stable/ +https://specs.status.im/spec/ https://specs.status.im/default.html diff --git a/spec/1.html b/spec/1.html new file mode 100644 index 0000000..c32a88a --- /dev/null +++ b/spec/1.html @@ -0,0 +1 @@ + 1/CLIENT - Status Specification 1/CLIENT | Status Specification Link Search Menu Expand Document

      1/CLIENT

      Version: 0.3

      Status: Stable

      Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Dean Eigenmann dean@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

      Abstract

      This specification describes how to write a Status client for communicating with other Status clients.

      This specification presents a reference implementation of the protocol 1 that is used in a command line client 2 and a mobile app 3.

      This document consists of two parts. The first outlines the specifications that have to be implemented in order to be a full Status client. The second gives a design rationale and answers some common questions.

      Table of Contents

      Introduction

      Protocol layers

      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 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
      Data and payloads End user functionality 1:1, group chat, public chat
      Data sync Data consistency MVDS.
      Secure transport Confidentiality, PFS, etc Double Ratchet
      Transport privacy Routing, Metadata protection Waku / Whisper
      P2P Overlay Overlay routing, NAT traversal devp2p

      Protobuf

      protobuf is used in different layers, version proto3 used is unless stated otherwise.

      Components

      P2P Overlay

      Status clients run on a public, permissionless peer-to-peer network, as specified by the devP2P network protocols. devP2P provides a protocol for node discovery which is in draft mode here. See more on node discovery and management in the next section.

      To communicate between Status nodes, the RLPx Transport Protocol, v5 is used, which allows for TCP-based communication between nodes.

      On top of this RLPx-based subprotocols are ran, the client SHOULD NOT use Whisper V6, the client SHOULD use Waku V1 for privacy-preserving messaging and efficient usage of a node’s bandwidth.

      Node discovery and roles

      There are four types of node roles:

      1. Bootstrap node
      2. Whisper/Waku relayer
      3. Mailserver (servers and clients)
      4. Mobile node (Status Clients)

      A standard Status client MUST implement both Whisper/Waku relayer and Mobile node node types. The other node types are optional, but it is RECOMMEND to implement a Mailserver client mode, otherwise the user experience is likely to be poor.

      Bootstrapping

      Bootstrap nodes allow Status nodes to discover and connect to other Status nodes in the network.

      Currently, Status Gmbh provides the main bootstrap nodes, but anyone can run these provided they are connected to the rest of the Whisper/Waku network.

      Status maintains a list of production fleet bootstrap nodes in the following locations:

      Hong Kong:

      • enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443
      • enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443

      Amsterdam:

      • enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443
      • enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443

      Central US:

      • enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443
      • enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443

      These bootstrap nodes MAY change and are not guaranteed to stay this way forever and at some point circumstances might force them to change.

      Discovery

      A Status client MUST discover or have a list of peers to connect to. Status uses a light discovery mechanism based on a combination of Discovery v5 and Rendezvous Protocol, (with some modifications). Additionally, some static nodes MAY also be used.

      A Status client MUST use at least one discovery method or use static nodes to communicate with other clients.

      Discovery V5 uses bootstrap nodes to discover other peers. Bootstrap nodes MUST support Discovery V5 protocol as well in order to provide peers. It is kademlia-based discovery mechanism and it might consume significant (at least on mobile) amount of network traffic to operate.

      In order to take advantage from simpler and more mobile-friendly peers discovery mechanism, i.e. Rendezvous protocol, one MUST provide a list of Rendezvous nodes which speak Rendezvous protocol. Rendezvous protocol is request-response discovery mechanism. It uses Ethereum Node Records (ENR) to report discovered peers.

      Both peers discovery mechanisms use topics to provide peers with certain capabilities. There is no point in returning peers that do not support a particular protocol. Status nodes that want to be discovered MUST register to Discovery V5 and/or Rendezvous with the whisper topic. Status nodes that are Mailservers and want to be discoverable MUST additionally register with the whispermail topic.

      It is RECOMMENDED to use both mechanisms but at the same time implement a structure called PeerPool. PeerPool is responsible for maintaining an optimal number of peers. For mobile nodes, there is no significant advantage to have more than 2-3 peers and one Mailserver. PeerPool can notify peers discovery protocol implementations that they should suspend their execution because the optimal number of peers is found. They should resume if the number of connected peers drops or a Mailserver disconnects.

      It is worth noticing that an efficient caching strategy MAY be of great use, especially, on mobile devices. Discovered peers can be cached as they rarely change and used when the client starts again. In such a case, there might be no need to even start peers discovery protocols because cached peers will satisfy the optimal number of peers.

      Alternatively, a client MAY rely exclusively on a list of static peers. This is the most efficient way because there are no peers discovery algorithm overhead introduced. The disadvantage is that these peers might be gone and without peers discovery mechanism, it won’t be possible to find new ones.

      The current list of static peers is published on https://fleets.status.im/. eth.prod is the current group of peers the official Status client uses. The others are test networks.

      Finally, Waku node addresses can be retrieved by traversing the merkle tree found at fleets.status.im, as described in EIP-1459.

      Mobile nodes

      A Mobile node is a Whisper and/or Waku node which connects to part of the respective Whisper and/or Waku network(s). A Mobile node MAY relay messages. See next section for more details on how to use Whisper and/or Waku to communicate with other Status nodes.

      Transport privacy and Whisper / Waku usage

      Once a Whisper and/or Waku node is up and running there are some specific settings required to communicate with other Status nodes.

      See 3/WHISPER-USAGE and 10/WAKU-USAGE for more details.

      For providing an offline inbox, see the complementary 4/WHISPER-MAILSERVER and 11/WAKU-MAILSERVER.

      Secure Transport

      In order to provide confidentiality, integrity, authentication and forward 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 for more.

      Data Sync

      MVDS is used for 1:1 and group chats, however it is currently not in use for public chats. Status payloads are serialized and then wrapped inside an MVDS message which is added to an MVDS payload, the node encrypts this payload (if necessary for 1-to-1 / group-chats) and sends it using Whisper or Waku which also encrypts it.

      Payloads and clients

      On top of secure transport, various types of data sync clients and the node uses payload formats for things like 1:1 chat, group chat and public chat. These have various degrees of standardization. Please refer to 6/PAYLOADS for more details.

      BIPs and EIPs Standards support

      For a list of EIPs and BIPs that SHOULD be supported by Status client, please see 8/EIPS.

      Security Considerations

      See Appendix A

      Design Rationale

      P2P Overlay

      Why devp2p? Why not use libp2p?

      At the time Status developed the main Status clients, devp2p was the most mature. However, in the future libp2p is likely to be used, as it’ll provide us with multiple transports, better protocol negotiation, NAT traversal, etc.

      For very experimental bridge support, see the bridge between libp2p and devp2p in Murmur.

      What about other RLPx subprotocols like LES, and Swarm?

      Status is primarily optimized for resource restricted devices, and at present time light client support for these protocols are suboptimal. This is a work in progress.

      For better Ethereum light client support, see Re-enable LES as option. For better Swarm support, see Swarm adaptive nodes.

      For transaction support, Status clients currently have to rely on Infura.

      Status clients currently do not offer native support for file storage.

      Why do you use Whisper?

      Whisper is one of the three parts of the vision of Ethereum as the world computer, Ethereum and Swarm being the other two. Status was started as an encapsulation of and a clear window to this world computer.

      Why do you use Waku?

      Waku is a direct upgrade and replacement for Whisper, the main motivation for developing and implementing Waku can be found in the Waku specs.

      Waku was created to incrementally improve in areas that Whisper is lacking in, with special attention to resource restricted devices. We specify the standard for Waku messages in order to ensure forward compatibility of different Waku clients, backwards compatibility with Whisper clients, as well as to allow multiple implementations of Waku and its capabilities. We also modify the language to be more unambiguous, concise and consistent.

      Considerable work has gone into the active development of Ethereum, in contrast Whisper is not currently under active development, and it has several drawbacks. Among others:

      • Whisper is very wasteful bandwidth-wise and doesn’t appear to be scalable
      • Proof of work is a poor spam protection mechanism for heterogeneous devices
      • The privacy guarantees provided are not rigorous
      • There are no incentives to run a node

      Finding a more suitable transport privacy is an ongoing research effort, together with Vac and other teams in the space.

      Why is PoW for Waku set so low?

      A higher PoW would be desirable, but this kills the battery on mobile phones, which is a prime target for Status clients.

      This means the network is currently vulnerable to DDoS attacks. Alternative methods of spam protection are currently being researched.

      Why do you not use Discovery v5 for node discovery?

      At the time of implementing dynamic node discovery, Discovery v5 wasn’t completed yet. Additionally, running a DHT on a mobile leads to slow node discovery, bad battery and poor bandwidth usage. Instead, each client can choose to turn on Discovery v5 for a short period until the node populates their peer list.

      For some further investigation, see here.

      I heard something about Mailservers being trusted somehow?

      In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it knows the bloom filter of the topics the node is interested in, when it is online as well as many metadata like IP address.

      Data sync

      Why is MVDS not used for public chats?

      Currently, public chats are broadcast-based, and there’s no direct way of finding out who is receiving messages. Hence there’s no clear group sync state context whereby participants can sync. Additionally, MVDS is currently not optimized for large group contexts, which means bandwidth usage will be a lot higher than reasonable. See P2P Data Sync for Mobile for more. This is an active area of research.

      Footnotes

      1. https://github.com/status-im/status-protocol-go/
      2. https://github.com/status-im/status-console-client/
      3. https://github.com/status-im/status-react/

      Appendix A: Security considerations

      There are several security considerations to take into account when running Status. Chief among them are: scalability, DDoS-resistance and privacy. These also vary depending on what capabilities are used, such as Mailserver, light node, and so on.

      Scalability and UX

      Bandwidth usage:

      In version 1 of Status, bandwidth usage is likely to be an issue. In Status version 1.1 this is partially addressed with Waku usage, see the theoretical scaling model.

      Mailserver High Availability requirement:

      A Mailserver has to be online to receive messages for other nodes, this puts a high availability requirement on it.

      Gossip-based routing:

      Use of gossip-based routing doesn’t necessarily scale. It means each node can see a message multiple times, and having too many light nodes can cause propagation probability that is too low. See Whisper vs PSS for more and a possible Kademlia based alternative.

      Lack of incentives:

      Status currently lacks incentives to run nodes, which means node operators are more likely to create centralized choke points.

      Privacy

      Light node privacy:

      The main privacy concern with light nodes is that directly connected peers will know that a message originates from them (as it are the only ones it sends). This means nodes can make assumptions about what messages (topics) their peers are interested in.

      Bloom filter privacy:

      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 trilemma.

      Mailserver client privacy:

      A Mailserver client has to trust a Mailserver, which means they can send direct traffic. This reveals what topics / bloom filter a node is interested in, along with its peerID (with IP).

      Privacy guarantees not rigorous:

      Privacy for Whisper or Waku hasn’t been studied rigorously for various threat models like global passive adversary, local active attacker, etc. This is unlike e.g. Tor and mixnets.

      Topic hygiene:

      Similar to bloom filter privacy, using a very specific topic reveals more information. See scalability model linked above.

      Spam resistance

      PoW bad for heterogeneous devices:

      Proof of work is a poor spam prevention mechanism. A mobile device can only have a very low PoW in order not to use too much CPU / burn up its phone battery. This means someone can spin up a powerful node and overwhelm the network.

      Mailserver trusted connection:

      A Mailserver has a direct TCP connection, which means they are trusted to send traffic. This means a malicious or malfunctioning Mailserver can overwhelm an individual node.

      Censorship resistance

      Devp2p TCP port blockable:

      By default Devp2p runs on port 30303, which is not commonly used for any other service. This means it is easy to censor, e.g. airport WiFi. This can be mitigated somewhat by running on e.g. port 80 or 443, but there are still outstanding issues. See libp2p and Tor’s Pluggable Transport for how this can be improved.

      See https://github.com/status-im/status-react/issues/6351 for some discussion.

      Acknowledgments

      Jacek Sieka

      Changelog

      Version 0.3

      Released May 22, 2020

      • Added that Waku SHOULD be used
      • Added that Whisper SHOULD NOT be used
      • Added language to include Waku in all relevant places
      • Change to keep Mailserver term consistent

      Copyright and related rights waived via CC0.

      diff --git a/stable/10.html b/spec/10.html similarity index 68% rename from stable/10.html rename to spec/10.html index ddadbd5..e26e14d 100644 --- a/stable/10.html +++ b/spec/10.html @@ -1,4 +1,4 @@ - 10/WAKU-USAGE - Status Specification 10/WAKU-USAGE | Status Specification Link Search Menu Expand Document

      10/WAKU-USAGE

      Version: 0.1

      Status: Stable

      Authors: Adam Babik adam@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

      Abstract

      Status uses Waku to provide privacy-preserving routing and messaging on top of devP2P. Waku uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Waku topic. This allows anyone to listen on a single channel.

      Additionally, since anyone can receive Waku envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper.

      Reason

      Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat.

      Terminology

      • Waku node: an Ethereum node with Waku V1 enabled
      • Waku network: a group of Waku nodes connected together through the internet connection and forming a graph
      • Message: a decrypted Waku message
      • Offline message: an archived envelope
      • Envelope: an encrypted message with metadata like topic and Time-To-Live

      Waku packets

      Packet Name Code References
      Status 0 Status, WAKU-1
      Messages 1 WAKU-1
      Batch Ack 11 Undocumented. Marked for Deprecation
      Message Response 12 WAKU-1
      Status Update 22 WAKU-1
      P2P Request Complete 125 4/WAKU-MAILSERVER
      P2P Request 126 4/WAKU-MAILSERVER, WAKU-1
      P2P Messages 127 4/WAKU-MAILSERVER, WAKU-1

      Waku node configuration

      A Waku node must be properly configured to receive messages from Status clients.

      Nodes use Waku’s Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings:

      • proof-of-work requirement not larger than 0.002 for payloads less than 50,000 bytes
      • proof-of-work requirement not larger than 0.000002 for payloads greater than or equal to 50,000 bytes
      • time-to-live not lower than 10 (in seconds)

      Status

      Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items:

      [
      +     10/WAKU-USAGE - Status Specification       10/WAKU-USAGE | Status Specification               Link      Search      Menu      Expand      Document       

      10/WAKU-USAGE

      Version: 0.1

      Status: Stable

      Authors: Adam Babik adam@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

      Abstract

      Status uses Waku to provide privacy-preserving routing and messaging on top of devP2P. Waku uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Waku topic. This allows anyone to listen on a single channel.

      Additionally, since anyone can receive Waku envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper.

      Reason

      Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat.

      Terminology

      • Waku node: an Ethereum node with Waku V1 enabled
      • Waku network: a group of Waku nodes connected together through the internet connection and forming a graph
      • Message: a decrypted Waku message
      • Offline message: an archived envelope
      • Envelope: an encrypted message with metadata like topic and Time-To-Live

      Waku packets

      Packet Name Code References
      Status 0 Status, WAKU-1
      Messages 1 WAKU-1
      Batch Ack 11 Undocumented. Marked for Deprecation
      Message Response 12 WAKU-1
      Status Update 22 WAKU-1
      P2P Request Complete 125 4/WAKU-MAILSERVER
      P2P Request 126 4/WAKU-MAILSERVER, WAKU-1
      P2P Messages 127 4/WAKU-MAILSERVER, WAKU-1

      Waku node configuration

      A Waku node must be properly configured to receive messages from Status clients.

      Nodes use Waku’s Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings:

      • proof-of-work requirement not larger than 0.002 for payloads less than 50,000 bytes
      • proof-of-work requirement not larger than 0.000002 for payloads greater than or equal to 50,000 bytes
      • time-to-live not lower than 10 (in seconds)

      Status

      Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items:

      [
         [ pow-requirement-key pow-requirement ]
         [ bloom-filter-key bloom-filter ]
         [ light-node-key light-node ]
      diff --git a/spec/11.html b/spec/11.html
      new file mode 100644
      index 0000000..3632886
      --- /dev/null
      +++ b/spec/11.html
      @@ -0,0 +1,3 @@
      +     11/WAKU-MAILSERVER - Status Specification       11/WAKU-MAILSERVER | Status Specification               Link      Search      Menu      Expand      Document       

      11/WAKU-MAILSERVER

      Version: 0.1

      Status: Stable

      Authors: Adam Babik adam@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

      Abstract

      Being mostly offline is an intrinsic property of mobile clients. They need to save network transfer and battery consumption to avoid spending too much money or constant charging. Waku protocol, on the other hand, is an online protocol. Messages are available in the Waku network only for short period of time calculate in seconds.

      Waku Mailserver is a specification that allows messages to be stored permanently and to allows the stored messages to be delivered to requesting client nodes, regardless if the messages are not available in the network due to the message TTL expiring.

      Mailserver

      From the network perspective, a Mailserver is just like any other Waku node. The only difference is that a Mailserver has the capability of archiving messages and delivering them to its peers on-demand.

      It is important to notice that a Mailserver will only handle requests from its direct peers and exchanged packets between a Mailserver and a peer are p2p messages.

      Archiving messages

      A node which wants to provide Mailserver functionality MUST store envelopes from incoming message packets (Waku packet-code 0x01). The envelopes can be stored in any format, however they MUST be serialized and deserialized to the Waku envelope format.

      A Mailserver SHOULD store envelopes for all topics to be generally useful for any peer, however for specific use cases it MAY store envelopes for a subset of topics.

      Requesting messages

      In order to request historic messages, a node MUST send a packet P2P Request (0x7e) to a peer providing Mailserver functionality. This packet requires one argument which MUST be a Waku envelope.

      In the Waku envelope’s payload section, there MUST be RLP-encoded information about the details of the request:

      [ Lower, Upper, Bloom, Limit, Cursor ]
      +

      Lower: 4-byte wide unsigned integer (UNIX time in seconds; oldest requested envelope’s creation time)
      Upper: 4-byte wide unsigned integer (UNIX time in seconds; newest requested envelope’s creation time)
      Bloom: 64-byte wide array of Waku topics encoded in a bloom filter to filter envelopes
      Limit: 4-byte wide unsigned integer limiting the number of returned envelopes
      Cursor: an array of a cursor returned from the previous request (optional)

      The Cursor field SHOULD be filled in if a number of envelopes between Lower and Upper is greater than Limit so that the requester can send another request using the obtained Cursor value. What exactly is in the Cursor is up to the implementation. The requester SHOULD NOT use a Cursor obtained from one Mailserver in a request to another Mailserver because the format or the result MAY be different.

      The envelope MUST be encrypted with a symmetric key agreed between the requester and the Mailserver.

      Receiving historic messages

      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 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.

      For a requester, to know that all messages have been sent by a Mailserver, it SHOULD handle P2P Request Complete code (0x7d). This code is followed by the following parameters:

      [ RequestID, LastEnvelopeHash, Cursor ]
      +
      • RequestID: 32-byte wide array with a Keccak-256 hash of the envelope containing the original request
      • LastEnvelopeHash: 32-byte wide array with a Keccak-256 hash of the last sent envelope for the request
      • Cursor: an array of a cursor returned from the previous request (optional)

      If Cursor is not empty, it means that not all messages were sent due to the set Limit in the request. One or more consecutive requests MAY be sent with Cursor field filled in order to receive the rest of the messages.

      Security considerations

      Confidentiality

      The node encrypts all Waku envelopes. A Mailserver node can not inspect their contents.

      Altruistic and centralized operator risk

      In order to be useful, a Mailserver SHOULD be online most of time. That means users either have to be a bit tech-savvy to run their own node, or rely on someone else to run it for them.

      Currently, one of Status’s legal entities provides Mailservers in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research.

      A Status client SHOULD allow the Mailserver selection to be customizable.

      Privacy concerns

      In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it will have access to the bloom filter of topics that the user is interested in, when it is online as well as many metadata like IP address.

      Denial-of-service

      Since a Mailserver is delivering expired envelopes and has a direct TCP connection with the recipient, the recipient is vulnerable to DoS attacks from a malicious Mailserver node.

      Changelog

      Version 0.1

      Released May 22, 2020

      • Created document
      • Forked from 4-whisper-mailserver
      • Change to keep Mailserver term consistent
      • Replaced Whisper references with Waku

      Copyright and related rights waived via CC0.

      diff --git a/spec/15.html b/spec/15.html new file mode 100644 index 0000000..ca25254 --- /dev/null +++ b/spec/15.html @@ -0,0 +1 @@ + 15/NOTIFICATIONS - Status Specification 15/NOTIFICATIONS | Status Specification Link Search Menu Expand Document

      15/NOTIFICATIONS

      Local Notifications

      A client should implement local notifications to offer notifications for any event in the app without the privacy cost and dependency on third party services. This means that the client should run a background service to continuously or periodically check for updates.

      Android

      Android allows running services on the device. When the user enables notifications, the client may start a ``Foreground Service`, and display a permanent notification indicating that the service is running, as required by Android guidelines. The service will simply keep the app from being killed by the system when it is in the background. The client will then be able to run in the background and display local notifications on events such as receiving a message in a one to one chat.

      To facilitate the implementation of local notifications, a node implementation such as status-go may provide a specific notification signal.

      Notifications are a separate process in Android, and interaction with a notification generates an Intent. To handle intents, the NewMessageSignalHandler may use a BroadcastReceiver, in order to update the state of local notifications when the user dismisses or tap a notification. If the user taps on a notification, the BroadcastReceiver generates a new intent to open the app should use universal links to get the user to the right place.

      iOS

      We are not able to offer local notifications on iOS because there is no concept of services in iOS. It offers background updates but they’re not consistently triggered, and cannot be relied upon. The system decides when the background updates are triggered and the heuristics aren’t known.

      Why is there no Push Notifications?

      Push Notifications, as offered by Apple and Google are a privacy concern, they require a centralized service that is aware of who the notification needs to be delivered to.

      Copyright and related rights waived via CC0.

      diff --git a/stable/2.html b/spec/2.html similarity index 52% rename from stable/2.html rename to spec/2.html index d7f6467..3337e54 100644 --- a/stable/2.html +++ b/spec/2.html @@ -1,4 +1,4 @@ - 2/ACCOUNT - Status Specification 2/ACCOUNT | Status Specification Link Search Menu Expand Document

      2/ACCOUNT

      Version: 0.4

      Status: Stable

      Authors: Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

      Abstract

      This specification explains what Status account is, and how a node establishes trust.

      Table of Contents

      Introduction

      The core concept of an account in Status is a set of cryptographic keypairs. Namely, the combination of the following:

      1. a Whisper/Waku chat identity keypair
      2. a set of cryptocurrency wallet keypairs

      The node verifies or derives everything else associated with the contact from the above items, including:

      • Ethereum address (future verification, currently the same base keypair)
      • 3 word mnemonic name
      • identicon
      • message signatures

      Initial Key Generation

      Public/Private Keypairs

      • An ECDSA (secp256k1 curve) public/private keypair MUST be generated via a BIP43 derived path from a BIP39 mnemonic seed phrase.
      • The default paths are defined as such:
        • Whisper/Waku Chat Key (IK): m/43'/60'/1581'/0'/0 (post Multiaccount integration)
        • Status Wallet paths: m/44'/60'/0'/0/i starting at i=0
          • following BIP44
          • NOTE: this (i=0) is also the current (and only) path for Whisper/Waku key before Multiaccount integration

      X3DH Prekey bundle creation

      • Status follows the X3DH prekey bundle scheme that Open Whisper Systems (not to be confused with the Whisper sub-protocol) outlines in their documentation with the following exceptions:
        • Status does not publish one-time keys OPK or perform DH including them, because there are no central servers in the Status implementation.
      • A client MUST create X3DH prekey bundles, each defined by the following items:
        • Identity Key: IK
        • Signed prekey: SPK
        • Prekey signature: Sig(IK, Encode(SPK))
        • Timestamp
      • These bundles are made available in a variety of ways, as defined in section 2.1.

      Account Broadcasting

      • A user is responsible for broadcasting certain information publicly so that others may contact them.

      X3DH Prekey bundles

      • A client SHOULD regenerate a new X3DH prekey bundle every 24 hours. This MAY be done in a lazy way, such that a client that does not come online past this time period does not regenerate or broadcast bundles.
      • The current bundle SHOULD be broadcast on a Whisper/Waku topic specific to his Identity Key, {IK}-contact-code, intermittently. This MAY be done every 6 hours.
      • A bundle SHOULD accompany every message sent.
      • TODO: retrieval of long-time offline users bundle via {IK}-contact-code

      Optional Account additions

      ENS Username

      • A user MAY register a public username on the Ethereum Name System (ENS). This username is a user-chosen subdomain of the stateofus.eth ENS registration that maps to their Whisper/Waku identity key (IK).

      Trust establishment

      Trust establishment deals with users verifying they are communicating with who they think they are.

      Terms Glossary

      term description
      privkey ECDSA secp256k1 private key
      pubkey ECDSA secp256k1 public key
      Whisper/Waku key pubkey for chat with HD derivation path m/43’/60’/1581’/0’/0

      Contact Discovery

      Public channels

      • Public group channels in Status are a broadcast/subscription system. All public messages are encrypted with a symmetric key derived from the channel name, K_{pub,sym}, which is publicly known.
      • A public group channel’s symmetric key MUST creation must follow the web3 API’s web3.ssh.generateSymKeyFromPassword function
      • In order to post to a public group channel, a client MUST have a valid account created.
      • In order to listen to a public group channel, a client must subscribe to the channel name. The sender of a message is derived from the message’s signature.
      • Discovery of channel names is not currently part of the protocol, and is typically done out of band. If a channel name is used that has not been used, it will be created.
      • A client MUST sign the message otherwise it will be discarded by the recipients.
      • channel name specification:
        • matches [a-z0-9\-]
        • is not a public key

      Private 1:1 messages

      This can be done in the following ways:

      1. scanning a user generated QR code
      2. discovery through the Status app
      3. asynchronous X3DH key exchange
      4. public key via public channel listening
        • status-react/src/status_im/contact_code/core.cljs
      5. contact codes
      6. decentralized storage (not implemented)
      7. Whisper/Waku

      Initial Key Exchange

      Bundles

      • An X3DH prekey bundle is defined as (code):
        Identity                // Identity key
        +     2/ACCOUNT - Status Specification       2/ACCOUNT | Status Specification               Link      Search      Menu      Expand      Document       

        2/ACCOUNT

        Version: 0.4

        Status: Stable

        Authors: Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

        Abstract

        This specification explains what Status account is, and how a node establishes trust.

        Table of Contents

        Introduction

        The core concept of an account in Status is a set of cryptographic keypairs. Namely, the combination of the following:

        1. a Whisper/Waku chat identity keypair
        2. a set of cryptocurrency wallet keypairs

        The node verifies or derives everything else associated with the contact from the above items, including:

        • Ethereum address (future verification, currently the same base keypair)
        • 3 word mnemonic name
        • identicon
        • message signatures

        Initial Key Generation

        Public/Private Keypairs

        • An ECDSA (secp256k1 curve) public/private keypair MUST be generated via a BIP43 derived path from a BIP39 mnemonic seed phrase.
        • The default paths are defined as such:
          • Whisper/Waku Chat Key (IK): m/43'/60'/1581'/0'/0 (post Multiaccount integration)
          • Status Wallet paths: m/44'/60'/0'/0/i starting at i=0
            • following BIP44
            • NOTE: this (i=0) is also the current (and only) path for Whisper/Waku key before Multiaccount integration

        X3DH Prekey bundle creation

        • Status follows the X3DH prekey bundle scheme that Open Whisper Systems (not to be confused with the Whisper sub-protocol) outlines in their documentation with the following exceptions:
          • Status does not publish one-time keys OPK or perform DH including them, because there are no central servers in the Status implementation.
        • A client MUST create X3DH prekey bundles, each defined by the following items:
          • Identity Key: IK
          • Signed prekey: SPK
          • Prekey signature: Sig(IK, Encode(SPK))
          • Timestamp
        • These bundles are made available in a variety of ways, as defined in section 2.1.

        Account Broadcasting

        • A user is responsible for broadcasting certain information publicly so that others may contact them.

        X3DH Prekey bundles

        • A client SHOULD regenerate a new X3DH prekey bundle every 24 hours. This MAY be done in a lazy way, such that a client that does not come online past this time period does not regenerate or broadcast bundles.
        • The current bundle SHOULD be broadcast on a Whisper/Waku topic specific to his Identity Key, {IK}-contact-code, intermittently. This MAY be done every 6 hours.
        • A bundle SHOULD accompany every message sent.
        • TODO: retrieval of long-time offline users bundle via {IK}-contact-code

        Optional Account additions

        ENS Username

        • A user MAY register a public username on the Ethereum Name System (ENS). This username is a user-chosen subdomain of the stateofus.eth ENS registration that maps to their Whisper/Waku identity key (IK).

        Trust establishment

        Trust establishment deals with users verifying they are communicating with who they think they are.

        Terms Glossary

        term description
        privkey ECDSA secp256k1 private key
        pubkey ECDSA secp256k1 public key
        Whisper/Waku key pubkey for chat with HD derivation path m/43’/60’/1581’/0’/0

        Contact Discovery

        Public channels

        • Public group channels in Status are a broadcast/subscription system. All public messages are encrypted with a symmetric key derived from the channel name, K_{pub,sym}, which is publicly known.
        • A public group channel’s symmetric key MUST creation must follow the web3 API’s web3.ssh.generateSymKeyFromPassword function
        • In order to post to a public group channel, a client MUST have a valid account created.
        • In order to listen to a public group channel, a client must subscribe to the channel name. The sender of a message is derived from the message’s signature.
        • Discovery of channel names is not currently part of the protocol, and is typically done out of band. If a channel name is used that has not been used, it will be created.
        • A client MUST sign the message otherwise it will be discarded by the recipients.
        • channel name specification:
          • matches [a-z0-9\-]
          • is not a public key

        Private 1:1 messages

        This can be done in the following ways:

        1. scanning a user generated QR code
        2. discovery through the Status app
        3. asynchronous X3DH key exchange
        4. public key via public channel listening
          • status-react/src/status_im/contact_code/core.cljs
        5. contact codes
        6. decentralized storage (not implemented)
        7. Whisper/Waku

        Initial Key Exchange

        Bundles

        • An X3DH prekey bundle is defined as (code):
          Identity                // Identity key
           SignedPreKeys           // a map of installation id to array of signed prekeys by that installation id
           Signature               // Prekey signature
           Timestamp               // When the bundle was lasted created locally
          diff --git a/stable/3.html b/spec/3.html
          similarity index 66%
          rename from stable/3.html
          rename to spec/3.html
          index 2ae374c..1e6a646 100644
          --- a/stable/3.html
          +++ b/spec/3.html
          @@ -1,4 +1,4 @@
          -     3/WHISPER-USAGE - Status Specification       3/WHISPER-USAGE | Status Specification               Link      Search      Menu      Expand      Document       

          3/WHISPER-USAGE

          Version: 0.3

          Status: Stable

          Authors: Adam Babik adam@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

          Abstract

          Status uses Whisper to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. This allows anyone to listen on a single channel.

          Additionally, since anyone can receive Whisper envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper.

          Finally, using an extension of Whisper provides the ability to do offline messaging.

          Reason

          Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat.

          Terminology

          • Whisper node: an Ethereum node with Whisper V6 enabled (in the case of go-ethereum, it’s --shh option)
          • Whisper network: a group of Whisper nodes connected together through the internet connection and forming a graph
          • Message: a decrypted Whisper message
          • Offline message: an archived envelope
          • Envelope: an encrypted message with metadata like topic and Time-To-Live

          Whisper packets

          Packet Name Code EIP-627 References
          Status 0 Handshake
          Messages 1 EIP-627
          PoW Requirement 2 EIP-627
          Bloom Filter 3 EIP-627
          Batch Ack 11 𝘅 Undocumented
          Message Response 12 𝘅 Undocumented
          P2P Sync Request 123 𝘅 Undocumented
          P2P Sync Response 124 𝘅 Undocumented
          P2P Request Complete 125 𝘅 4/WHISPER-MAILSERVER
          P2P Request 126 4/WHISPER-MAILSERVER
          P2P Messages 127 ✔/𝘅 (EIP-627 supports only single envelope in a packet) 4/WHISPER-MAILSERVER

          Whisper node configuration

          A Whisper node must be properly configured to receive messages from Status clients.

          Nodes use Whisper’s Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings:

          • proof-of-work requirement not larger than 0.002
          • time-to-live not lower than 10 (in seconds)

          Handshake

          Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items:

          [ protocolVersion, PoW, bloom, isLightNode, confirmationsEnabled, rateLimits ]
          +     3/WHISPER-USAGE - Status Specification       3/WHISPER-USAGE | Status Specification               Link      Search      Menu      Expand      Document       

          3/WHISPER-USAGE

          Version: 0.3

          Status: Stable

          Authors: Adam Babik adam@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

          Abstract

          Status uses Whisper to provide privacy-preserving routing and messaging on top of devP2P. Whisper uses topics to partition its messages, and these are leveraged for all chat capabilities. In the case of public chats, the channel name maps directly to its Whisper topic. This allows anyone to listen on a single channel.

          Additionally, since anyone can receive Whisper envelopes, it relies on the ability to decrypt messages to decide who is the correct recipient. Status nodes do not rely upon this property, and implement another secure transport layer on top of Whisper.

          Finally, using an extension of Whisper provides the ability to do offline messaging.

          Reason

          Provide routing, metadata protection, topic-based multicasting and basic encryption properties to support asynchronous chat.

          Terminology

          • Whisper node: an Ethereum node with Whisper V6 enabled (in the case of go-ethereum, it’s --shh option)
          • Whisper network: a group of Whisper nodes connected together through the internet connection and forming a graph
          • Message: a decrypted Whisper message
          • Offline message: an archived envelope
          • Envelope: an encrypted message with metadata like topic and Time-To-Live

          Whisper packets

          Packet Name Code EIP-627 References
          Status 0 Handshake
          Messages 1 EIP-627
          PoW Requirement 2 EIP-627
          Bloom Filter 3 EIP-627
          Batch Ack 11 𝘅 Undocumented
          Message Response 12 𝘅 Undocumented
          P2P Sync Request 123 𝘅 Undocumented
          P2P Sync Response 124 𝘅 Undocumented
          P2P Request Complete 125 𝘅 4/WHISPER-MAILSERVER
          P2P Request 126 4/WHISPER-MAILSERVER
          P2P Messages 127 ✔/𝘅 (EIP-627 supports only single envelope in a packet) 4/WHISPER-MAILSERVER

          Whisper node configuration

          A Whisper node must be properly configured to receive messages from Status clients.

          Nodes use Whisper’s Proof Of Work algorithm to deter denial of service and various spam/flood attacks against the Whisper network. The sender of a message must perform some work which in this case means processing time. Because Status’ main client is a mobile client, this easily leads to battery draining and poor performance of the app itself. Hence, all clients MUST use the following Whisper node settings:

          • proof-of-work requirement not larger than 0.002
          • time-to-live not lower than 10 (in seconds)

          Handshake

          Handshake is a RLP-encoded packet sent to a newly connected peer. It MUST start with a Status Code (0x00) and follow up with items:

          [ protocolVersion, PoW, bloom, isLightNode, confirmationsEnabled, rateLimits ]
           

          protocolVersion: version of the Whisper protocol PoW: minimum PoW accepted by the peer bloom: bloom filter of Whisper topic accepted by the peer isLightNode: when true, the peer won’t forward messages confirmationsEnabled: when true, the peer will send message confirmations rateLimits: is [ RateLimitIP, RateLimitPeerID, RateLimitTopic ] where each values is an integer with a number of accepted packets per second per IP, Peer ID, and Topic respectively

          bloom, isLightNode, confirmationsEnabled, and rateLimits are all optional arguments in the handshake. However, if an optional field is specified, all optional fields preceding it MUST also be specified in order to be unambiguous.

          Rate limiting

          In order to provide an optional very basic Denial-of-Service attack protection, each node SHOULD define its own rate limits. The rate limits SHOULD be applied on IPs, peer IDs, and envelope topics.

          Each node MAY decide to whitelist, i.e. do not rate limit, selected IPs or peer IDs.

          If a peer exceeds node’s rate limits, the connection between them MAY be dropped.

          Each node SHOULD broadcast its rate limits to its peers using rate limits packet code (0x14). The rate limits is RLP-encoded information:

          [ IP limits, PeerID limits, Topic limits ]
           

          IP limits: 4-byte wide unsigned integer PeerID limits: 4-byte wide unsigned integer Topic limits: 4-byte wide unsigned integer

          The rate limits MAY also be sent as an optional parameter in the handshake.

          Each node SHOULD respect rate limits advertised by its peers. The number of packets SHOULD be throttled in order not to exceed peer’s rate limits. If the limit gets exceeded, the connection MAY be dropped by the peer.

          Keys management

          The protocol requires a key (symmetric or asymmetric) for the following actions:

          • signing & verifying messages (asymmetric key)
          • encrypting & decrypting messages (asymmetric or symmetric key).

          As nodes require asymmetric keys and symmetric keys to process incoming messages, they must be available all the time and are stored in memory.

          Keys management for PFS is described in 5/SECURE-TRANSPORT.

          The Status protocols uses a few particular Whisper topics to achieve its goals.

          Contact code topic

          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.

          Contact code topic MUST be created following the algorithm below:

          contactCode := "0x" + hexEncode(activePublicKey) + "-contact-code"
           
          diff --git a/spec/4.html b/spec/4.html
          new file mode 100644
          index 0000000..0c8723a
          --- /dev/null
          +++ b/spec/4.html
          @@ -0,0 +1,3 @@
          +     4/WHISPER-MAILSERVER - Status Specification       4/WHISPER-MAILSERVER | Status Specification               Link      Search      Menu      Expand      Document       

          4/WHISPER-MAILSERVER

          Version: 0.3

          Status: Stable

          Authors: Adam Babik adam@status.im, Oskar Thorén oskar@status.im (alphabetical order)

          Abstract

          Being mostly offline is an intrinsic property of mobile clients. They need to save network transfer and battery consumption to avoid spending too much money or constant charging. Whisper protocol, on the other hand, is an online protocol. Messages are available in the Whisper network only for short period of time calculate in seconds.

          Whisper Mailserver is a Whisper extension that allows to store messages permanently and deliver them to the clients even though they are already not available in the network and expired.

          Mailserver

          From the network perspective, Mailserver is just like any other Whisper node. The only difference is that it has a capability of archiving messages and delivering them to its peers on-demand.

          It is important to notice that Mailserver will only handle requests from its direct peers and exchanged packets between Mailserver and a peer are p2p messages.

          Archiving messages

          A node which wants to provide Mailserver functionality MUST store envelopes from incoming message packets (Whisper packet-code 0x01). The envelopes can be stored in any format, however they MUST be serialized and deserialized to the Whisper envelope format.

          A Mailserver SHOULD store envelopes for all topics to be generally useful for any peer, however for specific use cases it MAY store envelopes for a subset of topics.

          Requesting messages

          In order to request historic messages, a node MUST send a packet P2P Request (0x7e) to a peer providing Mailserver functionality. This packet requires one argument which MUST be a Whisper envelope.

          In the Whisper envelope’s payload section, there MUST be RLP-encoded information about the details of the request:

          [ Lower, Upper, Bloom, Limit, Cursor ]
          +

          Lower: 4-byte wide unsigned integer (UNIX time in seconds; oldest requested envelope’s creation time)
          Upper: 4-byte wide unsigned integer (UNIX time in seconds; newest requested envelope’s creation time)
          Bloom: 64-byte wide array of Whisper topics encoded in a bloom filter to filter envelopes
          Limit: 4-byte wide unsigned integer limiting the number of returned envelopes
          Cursor: an array of a cursor returned from the previous request (optional)

          The Cursor field SHOULD be filled in if a number of envelopes between Lower and Upper is greater than Limit so that the requester can send another request using the obtained Cursor value. What exactly is in the Cursor is up to the implementation. The requester SHOULD NOT use a Cursor obtained from one Mailserver in a request to another Mailserver because the format or the result MAY be different.

          The envelope MUST be encrypted with a symmetric key agreed between the requester and Mailserver.

          Receiving historic messages

          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 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.

          For a requester, to know that all messages have been sent by Mailserver, it SHOULD handle P2P Request Complete code (0x7d). This code is followed by the following parameters:

          [ RequestID, LastEnvelopeHash, Cursor ]
          +

          RequestID: 32-byte wide array with a Keccak-256 hash of the envelope containing the original request
          LastEnvelopeHash: 32-byte wide array with a Keccak-256 hash of the last sent envelope for the request
          Cursor: an array of a cursor returned from the previous request (optional)

          If Cursor is not empty, it means that not all messages were sent due to the set Limit in the request. One or more consecutive requests MAY be sent with Cursor field filled in order to receive the rest of the messages.

          Security considerations

          Confidentiality

          The node encrypts all Whisper envelopes. A Mailserver node can not inspect their contents.

          Altruistic and centralized operator risk

          In order to be useful, a Mailserver SHOULD be online most of the time. That means users either have to be a bit tech-savvy to run their own node, or rely on someone else to run it for them.

          Currently, one of Status’s legal entities provides Mailservers in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research.

          A Status client SHOULD allow the Mailserver selection to be customizable.

          Privacy concerns

          In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it will have access to the bloom filter of topics that the user is interested in, when it is online as well as many metadata like IP address.

          Denial-of-service

          Since a Mailserver is delivering expired envelopes and has a direct TCP connection with the recipient, the recipient is vulnerable to DoS attacks from a malicious Mailserver node.

          Changelog

          Version 0.3

          Released May 22, 2020

          • Change to keep Mailserver term consistent

          Copyright and related rights waived via CC0.

          diff --git a/stable/5.html b/spec/5.html similarity index 59% rename from stable/5.html rename to spec/5.html index a829408..e5ff3e6 100644 --- a/stable/5.html +++ b/spec/5.html @@ -1,4 +1,4 @@ - 5/SECURE-TRANSPORT - Status Specification 5/SECURE-TRANSPORT | Status Specification Link Search Menu Expand Document

          5/SECURE-TRANSPORT

          Version: 0.3

          Status: Stable

          Authors: Andrea Piana andreap@status.im, Pedro Pombeiro pedro@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Dean Eigenmann dean@status.im

          Abstract

          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 and Double Ratchet specifications, with some adaptations to operate in a decentralized environment.

          Table of Contents

          Introduction

          This document describes how nodes establish a secure channel, and how various conversational security properties are achieved.

          Definitions

          • Perfect Forward Secrecy is a feature of specific key-agreement protocols which provide assurances that 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.

          Design Requirements

          • Confidentiality: The adversary should not be able to learn what data is being exchanged between two Status clients.
          • Authenticity: The adversary should not be able to cause either endpoint of a Status 1:1 chat to accept data from any third party as though it came from the other endpoint.
          • Forward Secrecy: The adversary should not be able to learn what data was exchanged between two Status clients if, at some later time, the adversary compromises one or both of the endpoint devices.
          • Integrity: The adversary should not be able to cause either endpoint of a Status 1:1 chat to accept data that has been tampered with.

          All of these properties are ensured by the use of Signal’s Double Ratchet

          Conventions

          Types used in this specification are defined using Protobuf.

          Transport Layer

          Whisper and Waku serves as the transport layers for the Status chat protocol.

          User flow for 1-to-1 communications

          Account generation

          See Account specification

          Account recovery

          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, 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

          All 1:1 and group chat messaging in Status is subject to end-to-end encryption to provide users with a strong degree of privacy and security. Public chat messages are publicly readable by anyone since there’s no permission model for who is participating in a public chat.

          The rest of this document is purely about 1:1 and private group chat. Private group chat largely reduces to 1:1 chat, since there’s a secure channel between each pair-wise participant.

          End-to-end encryption

          End-to-end encryption (E2EE) takes place between two clients. The main cryptographic protocol is a Status implementation of the Double Ratchet protocol, which is in turn derived from the Off-the-Record protocol, using a different ratchet. The transport protocol subsequently encrypt the message payload - Whisper/Waku (see section Transport Layer) -, using symmetric key encryption. Furthermore, Status uses the concept of prekeys (through the use of 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:

          • Whisper/Waku
            • AES-256-GCM
            • ECIES
            • ECDSA
            • KECCAK-256
          • X3DH
            • Elliptic curve Diffie-Hellman key exchange (secp256k1)
            • KECCAK-256
            • ECDSA
            • ECIES
          • Double Ratchet
            • HMAC-SHA-256 as MAC
            • Elliptic curve Diffie-Hellman key exchange (Curve25519)
            • AES-256-CTR with HMAC-SHA-256 and IV derived alongside an encryption key

            The node achieves key derivation using HKDF.

          Prekeys

          Every client initially generates some key material which is stored locally:

          • Identity keypair based on secp256k1 - IK
          • A signed prekey based on secp256k1 - SPK
          • A prekey signature - Sig(IK, Encode(SPK))

          More details can be found in the X3DH Prekey bundle creation section of 2/ACCOUNT.

          Prekey bundles can be extracted from any user’s messages, or found via searching for their specific topic, {IK}-contact-code.

          TODO: See below on bundle retrieval, this seems like enhancement and parameter for recommendation

          Bundle retrieval

          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, nodes typically use a shared server to store bundles and allow other users to download them upon request. Given Status’ goal of decentralization, Status chat clients cannot rely on the same type of infrastructure and must achieve the same result using other means. By growing order of convenience and security, the considered approaches are:

          • contact codes;
          • public and one-to-one chats;
          • QR codes;
          • ENS record;
          • Decentralized permanent storage (e.g. Swarm, IPFS).
          • Whisper/Waku

          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.

          1:1 chat contact request

          There are two phases in the initial negotiation of a 1:1 chat:

          1. Identity verification (e.g., face-to-face contact exchange through QR code, Identicon matching). A QR code serves two purposes simultaneously - identity verification and initial bundle retrieval;
          2. Asynchronous initial key exchange, using X3DH.

          For more information on account generation and trust establishment, see 2/ACCOUNT

          Initial key exchange flow (X3DH)

          Section 3 of the X3DH protocol describes the initial key exchange flow, with some additional context:

          • The users’ identity keys IK_A and IK_B correspond to their respective Status chat public keys;
          • Since it is not possible to guarantee that a prekey will be used only once in a decentralized world, the one-time prekey OPK_B is not used in this scenario;
          • Nodes do not send Bundles to a centralized server, but instead served in a decentralized way as described in bundle retrieval.

          Alice retrieves Bob’s prekey bundle, however it is not specific to Alice. It contains:

          (protobuf)

          // X3DH prekey bundle
          +     5/SECURE-TRANSPORT - Status Specification       5/SECURE-TRANSPORT | Status Specification               Link      Search      Menu      Expand      Document       

          5/SECURE-TRANSPORT

          Version: 0.3

          Status: Stable

          Authors: Andrea Piana andreap@status.im, Pedro Pombeiro pedro@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Dean Eigenmann dean@status.im

          Abstract

          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 and Double Ratchet specifications, with some adaptations to operate in a decentralized environment.

          Table of Contents

          Introduction

          This document describes how nodes establish a secure channel, and how various conversational security properties are achieved.

          Definitions

          • Perfect Forward Secrecy is a feature of specific key-agreement protocols which provide assurances that 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.

          Design Requirements

          • Confidentiality: The adversary should not be able to learn what data is being exchanged between two Status clients.
          • Authenticity: The adversary should not be able to cause either endpoint of a Status 1:1 chat to accept data from any third party as though it came from the other endpoint.
          • Forward Secrecy: The adversary should not be able to learn what data was exchanged between two Status clients if, at some later time, the adversary compromises one or both of the endpoint devices.
          • Integrity: The adversary should not be able to cause either endpoint of a Status 1:1 chat to accept data that has been tampered with.

          All of these properties are ensured by the use of Signal’s Double Ratchet

          Conventions

          Types used in this specification are defined using Protobuf.

          Transport Layer

          Whisper and Waku serves as the transport layers for the Status chat protocol.

          User flow for 1-to-1 communications

          Account generation

          See Account specification

          Account recovery

          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, 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

          All 1:1 and group chat messaging in Status is subject to end-to-end encryption to provide users with a strong degree of privacy and security. Public chat messages are publicly readable by anyone since there’s no permission model for who is participating in a public chat.

          The rest of this document is purely about 1:1 and private group chat. Private group chat largely reduces to 1:1 chat, since there’s a secure channel between each pair-wise participant.

          End-to-end encryption

          End-to-end encryption (E2EE) takes place between two clients. The main cryptographic protocol is a Status implementation of the Double Ratchet protocol, which is in turn derived from the Off-the-Record protocol, using a different ratchet. The transport protocol subsequently encrypt the message payload - Whisper/Waku (see section Transport Layer) -, using symmetric key encryption. Furthermore, Status uses the concept of prekeys (through the use of 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:

          • Whisper/Waku
            • AES-256-GCM
            • ECIES
            • ECDSA
            • KECCAK-256
          • X3DH
            • Elliptic curve Diffie-Hellman key exchange (secp256k1)
            • KECCAK-256
            • ECDSA
            • ECIES
          • Double Ratchet
            • HMAC-SHA-256 as MAC
            • Elliptic curve Diffie-Hellman key exchange (Curve25519)
            • AES-256-CTR with HMAC-SHA-256 and IV derived alongside an encryption key

            The node achieves key derivation using HKDF.

          Prekeys

          Every client initially generates some key material which is stored locally:

          • Identity keypair based on secp256k1 - IK
          • A signed prekey based on secp256k1 - SPK
          • A prekey signature - Sig(IK, Encode(SPK))

          More details can be found in the X3DH Prekey bundle creation section of 2/ACCOUNT.

          Prekey bundles can be extracted from any user’s messages, or found via searching for their specific topic, {IK}-contact-code.

          TODO: See below on bundle retrieval, this seems like enhancement and parameter for recommendation

          Bundle retrieval

          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, nodes typically use a shared server to store bundles and allow other users to download them upon request. Given Status’ goal of decentralization, Status chat clients cannot rely on the same type of infrastructure and must achieve the same result using other means. By growing order of convenience and security, the considered approaches are:

          • contact codes;
          • public and one-to-one chats;
          • QR codes;
          • ENS record;
          • Decentralized permanent storage (e.g. Swarm, IPFS).
          • Whisper/Waku

          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.

          1:1 chat contact request

          There are two phases in the initial negotiation of a 1:1 chat:

          1. Identity verification (e.g., face-to-face contact exchange through QR code, Identicon matching). A QR code serves two purposes simultaneously - identity verification and initial bundle retrieval;
          2. Asynchronous initial key exchange, using X3DH.

          For more information on account generation and trust establishment, see 2/ACCOUNT

          Initial key exchange flow (X3DH)

          Section 3 of the X3DH protocol describes the initial key exchange flow, with some additional context:

          • The users’ identity keys IK_A and IK_B correspond to their respective Status chat public keys;
          • Since it is not possible to guarantee that a prekey will be used only once in a decentralized world, the one-time prekey OPK_B is not used in this scenario;
          • Nodes do not send Bundles to a centralized server, but instead served in a decentralized way as described in bundle retrieval.

          Alice retrieves Bob’s prekey bundle, however it is not specific to Alice. It contains:

          (protobuf)

          // X3DH prekey bundle
           message Bundle {
           
             bytes identity = 1;
          diff --git a/stable/6.html b/spec/6.html
          similarity index 75%
          rename from stable/6.html
          rename to spec/6.html
          index d65deae..d729ab3 100644
          --- a/stable/6.html
          +++ b/spec/6.html
          @@ -1,4 +1,4 @@
          -     6/PAYLOADS - Status Specification       6/PAYLOADS | Status Specification               Link      Search      Menu      Expand      Document       

          6/PAYLOADS

          Version: 0.3

          Status: Stable

          Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Oskar Thorén oskar@status.im (alphabetical order)

          Abstract

          This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases.

          The payloads aims to be flexible enough to support messaging but also cases described in the Status Whitepaper as well as various clients created using different technologies.

          Table of Contents

          Introduction

          This document describes the payload format and some special considerations.

          Payload wrapper

          The node wraps all payloads in a protobuf record record:

          message ApplicationMetadataMessage {
          +     6/PAYLOADS - Status Specification       6/PAYLOADS | Status Specification               Link      Search      Menu      Expand      Document       

          6/PAYLOADS

          Version: 0.3

          Status: Stable

          Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Oskar Thorén oskar@status.im (alphabetical order)

          Abstract

          This specification describes how the payload of each message in Status looks like. It is primarily centered around chat and chat-related use cases.

          The payloads aims to be flexible enough to support messaging but also cases described in the Status Whitepaper as well as various clients created using different technologies.

          Table of Contents

          Introduction

          This document describes the payload format and some special considerations.

          Payload wrapper

          The node wraps all payloads in a protobuf record record:

          message ApplicationMetadataMessage {
             bytes signature = 1;
             bytes payload = 2;
           
          diff --git a/spec/8.html b/spec/8.html
          new file mode 100644
          index 0000000..95e9071
          --- /dev/null
          +++ b/spec/8.html
          @@ -0,0 +1 @@
          +     8/EIPS - Status Specification       8/EIPS | Status Specification               Link      Search      Menu      Expand      Document       

          8/EIPS

          Version: 0.2

          Status: Stable

          Authors: Ricardo Guilherme Schmidt ricardo3@status.im

          Abstract

          This specification describes how Status relates with EIPs.

          Table of Contents

          Introduction

          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

            Status v0 Status v1 Other State
          BIP32 N Y N stable
          BIP39 Y Y Y stable
          BIP43 N Y N stable
          BIP44 N Y N stable
          EIP20 Y Y Y stable
          EIP55 Y Y Y stable
          EIP67 P P N stable
          EIP137 P P N stable
          EIP155 Y Y Y stable
          EIP165 P N N stable
          EIP181 P N N stable
          EIP191 Y? N Y stable
          EIP627 Y Y N stable
          EIP681 Y N Y stable
          EIP712 P P Y stable
          EIP721 P P Y stable
          EIP831 N Y N stable
          EIP945 Y Y N stable
          EIP1102 Y Y Y stable
          EIP1193 Y Y Y stable
          EIP1577 Y P N stable
          EIP1581 N Y N stable
          EIP1459 N   N raw

          Components

          BIP32 - Hierarchical Deterministic Wallets

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
          Description: Enable wallets to derive multiple private keys from the same seed.
          Used for: Dependency of BIP39 and BIP43.

          BIP39 - Mnemonic code for generating deterministic keys

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
          Description: Enable wallet to create private key based on a safe seed phrase. Used for: Security and user experience.

          BIP43 - Purpose Field for Deterministic Wallets

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki
          Description: Enable wallet to create private keys branched for a specific purpose.
          Used for: Dependency of BIP44, uses “ethereum” coin.

          BIP44 - Multi-Account Hierarchy for Deterministic Wallets

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
          Description: Enable wallet to derive multiple accounts in top of BIP39.
          Used for: Privacy.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/constants.cljs#L240
          Observation: BIP44 don’t solve privacy issues regarding the transparency of transactions, therefore directly connected addresses through a transactions can be identifiable by a “network reconnaissance attack” over transaction history, this attack together with leakage of information from centralized services, such as exchanges, would be fatal against the whole privacy of users, regardless of BIP44.

          EIP20 - Fungible Token

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-20
          Description: Enable wallets to use tokens based on smart contracts compliant with this standard.
          Used for: Wallet feature.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs

          EIP55 - Mixed-case checksum address encoding

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-55
          Description: Checksum standard that uses lowercase and uppercase inside address hex value.
          Used for: Sanity check of forms using ethereum address.
          Related: https://github.com/status-im/status-react/issues/4959 https://github.com/status-im/status-react/issues/8707
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip55.cljs

          EIP67 - Standard URI scheme with metadata, value and byte code

          Support: Partial.
          Reference: https://github.com/ethereum/EIPs/issues/67
          Description: A standard way of creating Ethereum URIs for various use-cases.
          Used for: Legacy support.
          https://github.com/status-im/status-react/issues/875

          EIP137 - Ethereum Domain Name Service - Specification

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-137
          Description: Enable wallets to lookup ENS names.
          Used for: User experience, as a wallet and identity feature, usernames.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/ens.cljs#L86

          EIP155 - Simple replay attack protection

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-155
          Description: Defined chainId parameter in the singed ethereum transaction payload.
          Used for: Signing transactions, crucial to safety of users against replay attacks.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/core.cljs

          EIP165 - Standard Interface Detection

          Support: Dependency/Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-165
          Description: Standard interface for contract to answer if it supports other interfaces.
          Used for: Dependency of ENS and EIP721.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip165.cljs

          EIP181 - ENS support for reverse resolution of Ethereum addresses

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-181
          Description: Enable wallets to render reverse resolution of Ethereum addresses.
          Used for: Wallet feature.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/ens.cljs#L86

          EIP191 - Signed Message

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-191
          Description: Contract signature standard, adds an obligatory padding to signed message to differentiate from Ethereum Transaction messages.
          Used for: Dapp support, security, dependency of ERC712.

          EIP627 - Whisper Specification

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-627
          Description: format of Whisper messages within the ÐΞVp2p Wire Protocol.
          Used for: Chat protocol.

          EIP681 - URL Format for Transaction Requests

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-681 Description: A link that pop up a transaction in the wallet.
          Used for: Useful as QR code data for transaction requests, chat transaction requests and for dapp links to transaction requests.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip681.cljs
          Related: Issue #9183: URL Format for Transaction Requests (EIP681) is poorly supported https://github.com/status-im/status-react/pull/9240 https://github.com/status-im/status-react/issues/9238 https://github.com/status-im/status-react/issues/7214 https://github.com/status-im/status-react/issues/7325 https://github.com/status-im/status-react/issues/8150

          EIP712 - Typed Signed Message

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-712
          Description: Standardize types for contract signature, allowing users to easily inspect whats being signed.
          Used for: User experience, security.
          Related: https://github.com/status-im/status-react/issues/5461 https://github.com/status-im/status-react/commit/ba37f7b8d029d3358c7b284f6a2383b9ef9526c9

          EIP721 - Non Fungible Token

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-721
          Description: Enable wallets to use tokens based on smart contracts compliant with this standard.
          Used for: Wallet feature.
          Related: https://github.com/status-im/status-react/issues/8909
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/erc721.cljs https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs

          EIP945 - Web 3 QR Code Scanning API

          Support: Full.
          Reference: https://github.com/ethereum/EIPs/issues/945
          Used for: Sharing contactcode, reading transaction requests.
          Related: https://github.com/status-im/status-react/issues/5870

          EIP1102 - Opt-in account exposure

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-1102
          Description: Allow users to opt-in the exposure of their ethereum address to dapps they browse.
          Used for: Privacy, DApp support.
          Related: https://github.com/status-im/status-react/issues/7985

          EIP1193 - Ethereum Provider JavaScript API

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-1193
          Description: Allows dapps to recognize event changes on wallet.
          Used for: DApp support.
          Related: https://github.com/status-im/status-react/pull/7246

          EIP1577 - contenthash field for ENS

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-1577
          Description: Allows users browse ENS domains using contenthash standard.
          Used for: Browser, DApp support.
          Related: https://github.com/status-im/status-react/issues/6688
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/utils/contenthash.cljs https://github.com/status-im/status-react/blob/develop/test/cljs/status_im/test/utils/contenthash.cljs#L5

          EIP1581 - Non-wallet usage of keys derived from BIP-32 trees

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-1581
          Description: Allow wallet to derive keys that are less sensible (non wallet).
          Used for: Security (don’t reuse wallet key) and user experience (don’t request keycard every login).
          Related: https://github.com/status-im/status-react/issues/9088 https://github.com/status-im/status-react/pull/9096
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/constants.cljs#L242

          EIP1459 - Node Discovery via DNS

          Support: - Reference: https://eips.ethereum.org/EIPS/eip-1459 Description: Allows the storing and retrieving of nodes through merkle trees stored in TXT records of a domain. Used for: Finding Waku nodes. Related: - Sourcecode: -

          Copyright and related rights waived via CC0.

          diff --git a/stable/9.html b/spec/9.html similarity index 54% rename from stable/9.html rename to spec/9.html index 1b37cad..632871a 100644 --- a/stable/9.html +++ b/spec/9.html @@ -1,4 +1,4 @@ - 9/ETHEREUM-USAGE - Status Specification 9/ETHEREUM-USAGE | Status Specification Link Search Menu Expand Document

          9/ETHEREUM-USAGE

          Version: 0.1

          Status: Stable

          Authors: Andrea Maria Piana andreap@status.im

          Status interactions with the Ethereum blockchain

          This specification documents all the interactions that the Status client has with the Ethereum blockchain.

          All the interactions are made through JSON-RPC. Currently Infura is used. The client assumes high-availability, otherwise it will not be able to interact with the Ethereum blockchain. Status nodes rely on these Infura nodes to validate the integrity of the transaction and report a consistent history.

          Key handling is described here

          1. Wallet
          2. ENS

          Wallet

          The wallet in Status has two main components:

          1) Sending transactions 2) Fetching balance

          In the section below are described the RPC calls made the nodes, with a brief description of their functionality and how it is used by Status.

          1. Sending transactions
          2. Fetching balance

          Sending transactions

          EstimateGas

          EstimateGas tries to estimate the gas needed to execute a specific transaction based on the current pending state of the backend blockchain. There is no guarantee that this is the true gas limit requirement as other transactions may be added or removed by miners, but it should provide a basis for setting a reasonable default.

          func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error)
          +     9/ETHEREUM-USAGE - Status Specification       9/ETHEREUM-USAGE | Status Specification               Link      Search      Menu      Expand      Document       

          9/ETHEREUM-USAGE

          Version: 0.1

          Status: Stable

          Authors: Andrea Maria Piana andreap@status.im

          Status interactions with the Ethereum blockchain

          This specification documents all the interactions that the Status client has with the Ethereum blockchain.

          All the interactions are made through JSON-RPC. Currently Infura is used. The client assumes high-availability, otherwise it will not be able to interact with the Ethereum blockchain. Status nodes rely on these Infura nodes to validate the integrity of the transaction and report a consistent history.

          Key handling is described here

          1. Wallet
          2. ENS

          Wallet

          The wallet in Status has two main components:

          1) Sending transactions 2) Fetching balance

          In the section below are described the RPC calls made the nodes, with a brief description of their functionality and how it is used by Status.

          1. Sending transactions
          2. Fetching balance

          Sending transactions

          EstimateGas

          EstimateGas tries to estimate the gas needed to execute a specific transaction based on the current pending state of the backend blockchain. There is no guarantee that this is the true gas limit requirement as other transactions may be added or removed by miners, but it should provide a basis for setting a reasonable default.

          func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error)
           

          https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L499

          PendingNonceAt

          PendingNonceAt returns the account nonce of the given account in the pending state. This is the nonce that should be used for the next transaction.

          func (ec *Client) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
           

          https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L440

          SuggestGasPrice

          SuggestGasPrice retrieves the currently suggested gas price to allow a timely execution of a transaction.

          func (ec *Client) SuggestGasPrice(ctx context.Context) (*big.Int, error)
           

          https://github.com/ethereum/go-ethereum/blob/26d271dfbba1367326dec38068f9df828d462c61/ethclient/ethclient.go#L487

          SendTransaction

          SendTransaction injects a signed transaction into the pending pool for execution.

          If the transaction was a contract creation use the TransactionReceipt method to get the contract address after the transaction has been mined.

          func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error 
          diff --git a/spec/index.html b/spec/index.html
          new file mode 100644
          index 0000000..9362dcc
          --- /dev/null
          +++ b/spec/index.html
          @@ -0,0 +1 @@
          +     Stable specs - Status Specification       Stable specs | Status Specification               Link      Search      Menu      Expand      Document         
          diff --git a/stable/1.html b/stable/1.html
          deleted file mode 100644
          index 60f1e96..0000000
          --- a/stable/1.html
          +++ /dev/null
          @@ -1 +0,0 @@
          -     1/CLIENT - Status Specification       1/CLIENT | Status Specification               Link      Search      Menu      Expand      Document       

          1/CLIENT

          Version: 0.3

          Status: Stable

          Authors: Adam Babik adam@status.im, Andrea Maria Piana andreap@status.im, Dean Eigenmann dean@status.im, Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

          Abstract

          This specification describes how to write a Status client for communicating with other Status clients.

          This specification presents a reference implementation of the protocol 1 that is used in a command line client 2 and a mobile app 3.

          This document consists of two parts. The first outlines the specifications that have to be implemented in order to be a full Status client. The second gives a design rationale and answers some common questions.

          Table of Contents

          Introduction

          Protocol layers

          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 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
          Data and payloads End user functionality 1:1, group chat, public chat
          Data sync Data consistency MVDS.
          Secure transport Confidentiality, PFS, etc Double Ratchet
          Transport privacy Routing, Metadata protection Waku / Whisper
          P2P Overlay Overlay routing, NAT traversal devp2p

          Protobuf

          protobuf is used in different layers, version proto3 used is unless stated otherwise.

          Components

          P2P Overlay

          Status clients run on a public, permissionless peer-to-peer network, as specified by the devP2P network protocols. devP2P provides a protocol for node discovery which is in draft mode here. See more on node discovery and management in the next section.

          To communicate between Status nodes, the RLPx Transport Protocol, v5 is used, which allows for TCP-based communication between nodes.

          On top of this RLPx-based subprotocols are ran, the client SHOULD NOT use Whisper V6, the client SHOULD use Waku V1 for privacy-preserving messaging and efficient usage of a node’s bandwidth.

          Node discovery and roles

          There are four types of node roles:

          1. Bootstrap node
          2. Whisper/Waku relayer
          3. Mailserver (servers and clients)
          4. Mobile node (Status Clients)

          A standard Status client MUST implement both Whisper/Waku relayer and Mobile node node types. The other node types are optional, but it is RECOMMEND to implement a Mailserver client mode, otherwise the user experience is likely to be poor.

          Bootstrapping

          Bootstrap nodes allow Status nodes to discover and connect to other Status nodes in the network.

          Currently, Status Gmbh provides the main bootstrap nodes, but anyone can run these provided they are connected to the rest of the Whisper/Waku network.

          Status maintains a list of production fleet bootstrap nodes in the following locations:

          Hong Kong:

          • enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443
          • enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443

          Amsterdam:

          • enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@178.128.138.128:443
          • enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443

          Central US:

          • enode://32ff6d88760b0947a3dee54ceff4d8d7f0b4c023c6dad34568615fcae89e26cc2753f28f12485a4116c977be937a72665116596265aa0736b53d46b27446296a@34.70.75.208:443
          • enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443

          These bootstrap nodes MAY change and are not guaranteed to stay this way forever and at some point circumstances might force them to change.

          Discovery

          A Status client MUST discover or have a list of peers to connect to. Status uses a light discovery mechanism based on a combination of Discovery v5 and Rendezvous Protocol, (with some modifications). Additionally, some static nodes MAY also be used.

          A Status client MUST use at least one discovery method or use static nodes to communicate with other clients.

          Discovery V5 uses bootstrap nodes to discover other peers. Bootstrap nodes MUST support Discovery V5 protocol as well in order to provide peers. It is kademlia-based discovery mechanism and it might consume significant (at least on mobile) amount of network traffic to operate.

          In order to take advantage from simpler and more mobile-friendly peers discovery mechanism, i.e. Rendezvous protocol, one MUST provide a list of Rendezvous nodes which speak Rendezvous protocol. Rendezvous protocol is request-response discovery mechanism. It uses Ethereum Node Records (ENR) to report discovered peers.

          Both peers discovery mechanisms use topics to provide peers with certain capabilities. There is no point in returning peers that do not support a particular protocol. Status nodes that want to be discovered MUST register to Discovery V5 and/or Rendezvous with the whisper topic. Status nodes that are Mailservers and want to be discoverable MUST additionally register with the whispermail topic.

          It is RECOMMENDED to use both mechanisms but at the same time implement a structure called PeerPool. PeerPool is responsible for maintaining an optimal number of peers. For mobile nodes, there is no significant advantage to have more than 2-3 peers and one Mailserver. PeerPool can notify peers discovery protocol implementations that they should suspend their execution because the optimal number of peers is found. They should resume if the number of connected peers drops or a Mailserver disconnects.

          It is worth noticing that an efficient caching strategy MAY be of great use, especially, on mobile devices. Discovered peers can be cached as they rarely change and used when the client starts again. In such a case, there might be no need to even start peers discovery protocols because cached peers will satisfy the optimal number of peers.

          Alternatively, a client MAY rely exclusively on a list of static peers. This is the most efficient way because there are no peers discovery algorithm overhead introduced. The disadvantage is that these peers might be gone and without peers discovery mechanism, it won’t be possible to find new ones.

          The current list of static peers is published on https://fleets.status.im/. eth.prod is the current group of peers the official Status client uses. The others are test networks.

          Finally, Waku node addresses can be retrieved by traversing the merkle tree found at fleets.status.im, as described in EIP-1459.

          Mobile nodes

          A Mobile node is a Whisper and/or Waku node which connects to part of the respective Whisper and/or Waku network(s). A Mobile node MAY relay messages. See next section for more details on how to use Whisper and/or Waku to communicate with other Status nodes.

          Transport privacy and Whisper / Waku usage

          Once a Whisper and/or Waku node is up and running there are some specific settings required to communicate with other Status nodes.

          See 3/WHISPER-USAGE and 10/WAKU-USAGE for more details.

          For providing an offline inbox, see the complementary 4/WHISPER-MAILSERVER and 11/WAKU-MAILSERVER.

          Secure Transport

          In order to provide confidentiality, integrity, authentication and forward 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 for more.

          Data Sync

          MVDS is used for 1:1 and group chats, however it is currently not in use for public chats. Status payloads are serialized and then wrapped inside an MVDS message which is added to an MVDS payload, the node encrypts this payload (if necessary for 1-to-1 / group-chats) and sends it using Whisper or Waku which also encrypts it.

          Payloads and clients

          On top of secure transport, various types of data sync clients and the node uses payload formats for things like 1:1 chat, group chat and public chat. These have various degrees of standardization. Please refer to 6/PAYLOADS for more details.

          BIPs and EIPs Standards support

          For a list of EIPs and BIPs that SHOULD be supported by Status client, please see 8/EIPS.

          Security Considerations

          See Appendix A

          Design Rationale

          P2P Overlay

          Why devp2p? Why not use libp2p?

          At the time Status developed the main Status clients, devp2p was the most mature. However, in the future libp2p is likely to be used, as it’ll provide us with multiple transports, better protocol negotiation, NAT traversal, etc.

          For very experimental bridge support, see the bridge between libp2p and devp2p in Murmur.

          What about other RLPx subprotocols like LES, and Swarm?

          Status is primarily optimized for resource restricted devices, and at present time light client support for these protocols are suboptimal. This is a work in progress.

          For better Ethereum light client support, see Re-enable LES as option. For better Swarm support, see Swarm adaptive nodes.

          For transaction support, Status clients currently have to rely on Infura.

          Status clients currently do not offer native support for file storage.

          Why do you use Whisper?

          Whisper is one of the three parts of the vision of Ethereum as the world computer, Ethereum and Swarm being the other two. Status was started as an encapsulation of and a clear window to this world computer.

          Why do you use Waku?

          Waku is a direct upgrade and replacement for Whisper, the main motivation for developing and implementing Waku can be found in the Waku specs.

          Waku was created to incrementally improve in areas that Whisper is lacking in, with special attention to resource restricted devices. We specify the standard for Waku messages in order to ensure forward compatibility of different Waku clients, backwards compatibility with Whisper clients, as well as to allow multiple implementations of Waku and its capabilities. We also modify the language to be more unambiguous, concise and consistent.

          Considerable work has gone into the active development of Ethereum, in contrast Whisper is not currently under active development, and it has several drawbacks. Among others:

          • Whisper is very wasteful bandwidth-wise and doesn’t appear to be scalable
          • Proof of work is a poor spam protection mechanism for heterogeneous devices
          • The privacy guarantees provided are not rigorous
          • There are no incentives to run a node

          Finding a more suitable transport privacy is an ongoing research effort, together with Vac and other teams in the space.

          Why is PoW for Waku set so low?

          A higher PoW would be desirable, but this kills the battery on mobile phones, which is a prime target for Status clients.

          This means the network is currently vulnerable to DDoS attacks. Alternative methods of spam protection are currently being researched.

          Why do you not use Discovery v5 for node discovery?

          At the time of implementing dynamic node discovery, Discovery v5 wasn’t completed yet. Additionally, running a DHT on a mobile leads to slow node discovery, bad battery and poor bandwidth usage. Instead, each client can choose to turn on Discovery v5 for a short period until the node populates their peer list.

          For some further investigation, see here.

          I heard something about Mailservers being trusted somehow?

          In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it knows the bloom filter of the topics the node is interested in, when it is online as well as many metadata like IP address.

          Data sync

          Why is MVDS not used for public chats?

          Currently, public chats are broadcast-based, and there’s no direct way of finding out who is receiving messages. Hence there’s no clear group sync state context whereby participants can sync. Additionally, MVDS is currently not optimized for large group contexts, which means bandwidth usage will be a lot higher than reasonable. See P2P Data Sync for Mobile for more. This is an active area of research.

          Footnotes

          1. https://github.com/status-im/status-protocol-go/
          2. https://github.com/status-im/status-console-client/
          3. https://github.com/status-im/status-react/

          Appendix A: Security considerations

          There are several security considerations to take into account when running Status. Chief among them are: scalability, DDoS-resistance and privacy. These also vary depending on what capabilities are used, such as Mailserver, light node, and so on.

          Scalability and UX

          Bandwidth usage:

          In version 1 of Status, bandwidth usage is likely to be an issue. In Status version 1.1 this is partially addressed with Waku usage, see the theoretical scaling model.

          Mailserver High Availability requirement:

          A Mailserver has to be online to receive messages for other nodes, this puts a high availability requirement on it.

          Gossip-based routing:

          Use of gossip-based routing doesn’t necessarily scale. It means each node can see a message multiple times, and having too many light nodes can cause propagation probability that is too low. See Whisper vs PSS for more and a possible Kademlia based alternative.

          Lack of incentives:

          Status currently lacks incentives to run nodes, which means node operators are more likely to create centralized choke points.

          Privacy

          Light node privacy:

          The main privacy concern with light nodes is that directly connected peers will know that a message originates from them (as it are the only ones it sends). This means nodes can make assumptions about what messages (topics) their peers are interested in.

          Bloom filter privacy:

          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 trilemma.

          Mailserver client privacy:

          A Mailserver client has to trust a Mailserver, which means they can send direct traffic. This reveals what topics / bloom filter a node is interested in, along with its peerID (with IP).

          Privacy guarantees not rigorous:

          Privacy for Whisper or Waku hasn’t been studied rigorously for various threat models like global passive adversary, local active attacker, etc. This is unlike e.g. Tor and mixnets.

          Topic hygiene:

          Similar to bloom filter privacy, using a very specific topic reveals more information. See scalability model linked above.

          Spam resistance

          PoW bad for heterogeneous devices:

          Proof of work is a poor spam prevention mechanism. A mobile device can only have a very low PoW in order not to use too much CPU / burn up its phone battery. This means someone can spin up a powerful node and overwhelm the network.

          Mailserver trusted connection:

          A Mailserver has a direct TCP connection, which means they are trusted to send traffic. This means a malicious or malfunctioning Mailserver can overwhelm an individual node.

          Censorship resistance

          Devp2p TCP port blockable:

          By default Devp2p runs on port 30303, which is not commonly used for any other service. This means it is easy to censor, e.g. airport WiFi. This can be mitigated somewhat by running on e.g. port 80 or 443, but there are still outstanding issues. See libp2p and Tor’s Pluggable Transport for how this can be improved.

          See https://github.com/status-im/status-react/issues/6351 for some discussion.

          Acknowledgments

          Jacek Sieka

          Changelog

          Version 0.3

          Released May 22, 2020

          • Added that Waku SHOULD be used
          • Added that Whisper SHOULD NOT be used
          • Added language to include Waku in all relevant places
          • Change to keep Mailserver term consistent

          Copyright and related rights waived via CC0.

          diff --git a/stable/11.html b/stable/11.html deleted file mode 100644 index f4dc8b0..0000000 --- a/stable/11.html +++ /dev/null @@ -1,3 +0,0 @@ - 11/WAKU-MAILSERVER - Status Specification 11/WAKU-MAILSERVER | Status Specification Link Search Menu Expand Document

          11/WAKU-MAILSERVER

          Version: 0.1

          Status: Stable

          Authors: Adam Babik adam@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)

          Abstract

          Being mostly offline is an intrinsic property of mobile clients. They need to save network transfer and battery consumption to avoid spending too much money or constant charging. Waku protocol, on the other hand, is an online protocol. Messages are available in the Waku network only for short period of time calculate in seconds.

          Waku Mailserver is a specification that allows messages to be stored permanently and to allows the stored messages to be delivered to requesting client nodes, regardless if the messages are not available in the network due to the message TTL expiring.

          Mailserver

          From the network perspective, a Mailserver is just like any other Waku node. The only difference is that a Mailserver has the capability of archiving messages and delivering them to its peers on-demand.

          It is important to notice that a Mailserver will only handle requests from its direct peers and exchanged packets between a Mailserver and a peer are p2p messages.

          Archiving messages

          A node which wants to provide Mailserver functionality MUST store envelopes from incoming message packets (Waku packet-code 0x01). The envelopes can be stored in any format, however they MUST be serialized and deserialized to the Waku envelope format.

          A Mailserver SHOULD store envelopes for all topics to be generally useful for any peer, however for specific use cases it MAY store envelopes for a subset of topics.

          Requesting messages

          In order to request historic messages, a node MUST send a packet P2P Request (0x7e) to a peer providing Mailserver functionality. This packet requires one argument which MUST be a Waku envelope.

          In the Waku envelope’s payload section, there MUST be RLP-encoded information about the details of the request:

          [ Lower, Upper, Bloom, Limit, Cursor ]
          -

          Lower: 4-byte wide unsigned integer (UNIX time in seconds; oldest requested envelope’s creation time)
          Upper: 4-byte wide unsigned integer (UNIX time in seconds; newest requested envelope’s creation time)
          Bloom: 64-byte wide array of Waku topics encoded in a bloom filter to filter envelopes
          Limit: 4-byte wide unsigned integer limiting the number of returned envelopes
          Cursor: an array of a cursor returned from the previous request (optional)

          The Cursor field SHOULD be filled in if a number of envelopes between Lower and Upper is greater than Limit so that the requester can send another request using the obtained Cursor value. What exactly is in the Cursor is up to the implementation. The requester SHOULD NOT use a Cursor obtained from one Mailserver in a request to another Mailserver because the format or the result MAY be different.

          The envelope MUST be encrypted with a symmetric key agreed between the requester and the Mailserver.

          Receiving historic messages

          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 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.

          For a requester, to know that all messages have been sent by a Mailserver, it SHOULD handle P2P Request Complete code (0x7d). This code is followed by the following parameters:

          [ RequestID, LastEnvelopeHash, Cursor ]
          -
          • RequestID: 32-byte wide array with a Keccak-256 hash of the envelope containing the original request
          • LastEnvelopeHash: 32-byte wide array with a Keccak-256 hash of the last sent envelope for the request
          • Cursor: an array of a cursor returned from the previous request (optional)

          If Cursor is not empty, it means that not all messages were sent due to the set Limit in the request. One or more consecutive requests MAY be sent with Cursor field filled in order to receive the rest of the messages.

          Security considerations

          Confidentiality

          The node encrypts all Waku envelopes. A Mailserver node can not inspect their contents.

          Altruistic and centralized operator risk

          In order to be useful, a Mailserver SHOULD be online most of time. That means users either have to be a bit tech-savvy to run their own node, or rely on someone else to run it for them.

          Currently, one of Status’s legal entities provides Mailservers in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research.

          A Status client SHOULD allow the Mailserver selection to be customizable.

          Privacy concerns

          In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it will have access to the bloom filter of topics that the user is interested in, when it is online as well as many metadata like IP address.

          Denial-of-service

          Since a Mailserver is delivering expired envelopes and has a direct TCP connection with the recipient, the recipient is vulnerable to DoS attacks from a malicious Mailserver node.

          Changelog

          Version 0.1

          Released May 22, 2020

          • Created document
          • Forked from 4-whisper-mailserver
          • Change to keep Mailserver term consistent
          • Replaced Whisper references with Waku

          Copyright and related rights waived via CC0.

          diff --git a/stable/15.html b/stable/15.html deleted file mode 100644 index cf504a0..0000000 --- a/stable/15.html +++ /dev/null @@ -1 +0,0 @@ - 15/NOTIFICATIONS - Status Specification 15/NOTIFICATIONS | Status Specification Link Search Menu Expand Document

          15/NOTIFICATIONS

          Local Notifications

          A client should implement local notifications to offer notifications for any event in the app without the privacy cost and dependency on third party services. This means that the client should run a background service to continuously or periodically check for updates.

          Android

          Android allows running services on the device. When the user enables notifications, the client may start a ``Foreground Service`, and display a permanent notification indicating that the service is running, as required by Android guidelines. The service will simply keep the app from being killed by the system when it is in the background. The client will then be able to run in the background and display local notifications on events such as receiving a message in a one to one chat.

          To facilitate the implementation of local notifications, a node implementation such as status-go may provide a specific notification signal.

          Notifications are a separate process in Android, and interaction with a notification generates an Intent. To handle intents, the NewMessageSignalHandler may use a BroadcastReceiver, in order to update the state of local notifications when the user dismisses or tap a notification. If the user taps on a notification, the BroadcastReceiver generates a new intent to open the app should use universal links to get the user to the right place.

          iOS

          We are not able to offer local notifications on iOS because there is no concept of services in iOS. It offers background updates but they’re not consistently triggered, and cannot be relied upon. The system decides when the background updates are triggered and the heuristics aren’t known.

          Why is there no Push Notifications?

          Push Notifications, as offered by Apple and Google are a privacy concern, they require a centralized service that is aware of who the notification needs to be delivered to.

          Copyright and related rights waived via CC0.

          diff --git a/stable/4.html b/stable/4.html deleted file mode 100644 index 604f2c6..0000000 --- a/stable/4.html +++ /dev/null @@ -1,3 +0,0 @@ - 4/WHISPER-MAILSERVER - Status Specification 4/WHISPER-MAILSERVER | Status Specification Link Search Menu Expand Document

          4/WHISPER-MAILSERVER

          Version: 0.3

          Status: Stable

          Authors: Adam Babik adam@status.im, Oskar Thorén oskar@status.im (alphabetical order)

          Abstract

          Being mostly offline is an intrinsic property of mobile clients. They need to save network transfer and battery consumption to avoid spending too much money or constant charging. Whisper protocol, on the other hand, is an online protocol. Messages are available in the Whisper network only for short period of time calculate in seconds.

          Whisper Mailserver is a Whisper extension that allows to store messages permanently and deliver them to the clients even though they are already not available in the network and expired.

          Mailserver

          From the network perspective, Mailserver is just like any other Whisper node. The only difference is that it has a capability of archiving messages and delivering them to its peers on-demand.

          It is important to notice that Mailserver will only handle requests from its direct peers and exchanged packets between Mailserver and a peer are p2p messages.

          Archiving messages

          A node which wants to provide Mailserver functionality MUST store envelopes from incoming message packets (Whisper packet-code 0x01). The envelopes can be stored in any format, however they MUST be serialized and deserialized to the Whisper envelope format.

          A Mailserver SHOULD store envelopes for all topics to be generally useful for any peer, however for specific use cases it MAY store envelopes for a subset of topics.

          Requesting messages

          In order to request historic messages, a node MUST send a packet P2P Request (0x7e) to a peer providing Mailserver functionality. This packet requires one argument which MUST be a Whisper envelope.

          In the Whisper envelope’s payload section, there MUST be RLP-encoded information about the details of the request:

          [ Lower, Upper, Bloom, Limit, Cursor ]
          -

          Lower: 4-byte wide unsigned integer (UNIX time in seconds; oldest requested envelope’s creation time)
          Upper: 4-byte wide unsigned integer (UNIX time in seconds; newest requested envelope’s creation time)
          Bloom: 64-byte wide array of Whisper topics encoded in a bloom filter to filter envelopes
          Limit: 4-byte wide unsigned integer limiting the number of returned envelopes
          Cursor: an array of a cursor returned from the previous request (optional)

          The Cursor field SHOULD be filled in if a number of envelopes between Lower and Upper is greater than Limit so that the requester can send another request using the obtained Cursor value. What exactly is in the Cursor is up to the implementation. The requester SHOULD NOT use a Cursor obtained from one Mailserver in a request to another Mailserver because the format or the result MAY be different.

          The envelope MUST be encrypted with a symmetric key agreed between the requester and Mailserver.

          Receiving historic messages

          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 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.

          For a requester, to know that all messages have been sent by Mailserver, it SHOULD handle P2P Request Complete code (0x7d). This code is followed by the following parameters:

          [ RequestID, LastEnvelopeHash, Cursor ]
          -

          RequestID: 32-byte wide array with a Keccak-256 hash of the envelope containing the original request
          LastEnvelopeHash: 32-byte wide array with a Keccak-256 hash of the last sent envelope for the request
          Cursor: an array of a cursor returned from the previous request (optional)

          If Cursor is not empty, it means that not all messages were sent due to the set Limit in the request. One or more consecutive requests MAY be sent with Cursor field filled in order to receive the rest of the messages.

          Security considerations

          Confidentiality

          The node encrypts all Whisper envelopes. A Mailserver node can not inspect their contents.

          Altruistic and centralized operator risk

          In order to be useful, a Mailserver SHOULD be online most of the time. That means users either have to be a bit tech-savvy to run their own node, or rely on someone else to run it for them.

          Currently, one of Status’s legal entities provides Mailservers in an altruistic manner, but this is suboptimal from a decentralization, continuance and risk point of view. Coming up with a better system for this is ongoing research.

          A Status client SHOULD allow the Mailserver selection to be customizable.

          Privacy concerns

          In order to use a Mailserver, a given node needs to connect to it directly, i.e. add the Mailserver as its peer and mark it as trusted. This means that the Mailserver is able to send direct p2p messages to the node instead of broadcasting them. Effectively, it will have access to the bloom filter of topics that the user is interested in, when it is online as well as many metadata like IP address.

          Denial-of-service

          Since a Mailserver is delivering expired envelopes and has a direct TCP connection with the recipient, the recipient is vulnerable to DoS attacks from a malicious Mailserver node.

          Changelog

          Version 0.3

          Released May 22, 2020

          • Change to keep Mailserver term consistent

          Copyright and related rights waived via CC0.

          diff --git a/stable/8.html b/stable/8.html deleted file mode 100644 index 243fb2a..0000000 --- a/stable/8.html +++ /dev/null @@ -1 +0,0 @@ - 8/EIPS - Status Specification 8/EIPS | Status Specification Link Search Menu Expand Document

          8/EIPS

          Version: 0.2

          Status: Stable

          Authors: Ricardo Guilherme Schmidt ricardo3@status.im

          Abstract

          This specification describes how Status relates with EIPs.

          Table of Contents

          Introduction

          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

            Status v0 Status v1 Other State
          BIP32 N Y N stable
          BIP39 Y Y Y stable
          BIP43 N Y N stable
          BIP44 N Y N stable
          EIP20 Y Y Y stable
          EIP55 Y Y Y stable
          EIP67 P P N stable
          EIP137 P P N stable
          EIP155 Y Y Y stable
          EIP165 P N N stable
          EIP181 P N N stable
          EIP191 Y? N Y stable
          EIP627 Y Y N stable
          EIP681 Y N Y stable
          EIP712 P P Y stable
          EIP721 P P Y stable
          EIP831 N Y N stable
          EIP945 Y Y N stable
          EIP1102 Y Y Y stable
          EIP1193 Y Y Y stable
          EIP1577 Y P N stable
          EIP1581 N Y N stable
          EIP1459 N   N raw

          Components

          BIP32 - Hierarchical Deterministic Wallets

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
          Description: Enable wallets to derive multiple private keys from the same seed.
          Used for: Dependency of BIP39 and BIP43.

          BIP39 - Mnemonic code for generating deterministic keys

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
          Description: Enable wallet to create private key based on a safe seed phrase. Used for: Security and user experience.

          BIP43 - Purpose Field for Deterministic Wallets

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki
          Description: Enable wallet to create private keys branched for a specific purpose.
          Used for: Dependency of BIP44, uses “ethereum” coin.

          BIP44 - Multi-Account Hierarchy for Deterministic Wallets

          Support: Dependency.
          Reference: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
          Description: Enable wallet to derive multiple accounts in top of BIP39.
          Used for: Privacy.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/constants.cljs#L240
          Observation: BIP44 don’t solve privacy issues regarding the transparency of transactions, therefore directly connected addresses through a transactions can be identifiable by a “network reconnaissance attack” over transaction history, this attack together with leakage of information from centralized services, such as exchanges, would be fatal against the whole privacy of users, regardless of BIP44.

          EIP20 - Fungible Token

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-20
          Description: Enable wallets to use tokens based on smart contracts compliant with this standard.
          Used for: Wallet feature.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs

          EIP55 - Mixed-case checksum address encoding

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-55
          Description: Checksum standard that uses lowercase and uppercase inside address hex value.
          Used for: Sanity check of forms using ethereum address.
          Related: https://github.com/status-im/status-react/issues/4959 https://github.com/status-im/status-react/issues/8707
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip55.cljs

          EIP67 - Standard URI scheme with metadata, value and byte code

          Support: Partial.
          Reference: https://github.com/ethereum/EIPs/issues/67
          Description: A standard way of creating Ethereum URIs for various use-cases.
          Used for: Legacy support.
          https://github.com/status-im/status-react/issues/875

          EIP137 - Ethereum Domain Name Service - Specification

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-137
          Description: Enable wallets to lookup ENS names.
          Used for: User experience, as a wallet and identity feature, usernames.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/ens.cljs#L86

          EIP155 - Simple replay attack protection

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-155
          Description: Defined chainId parameter in the singed ethereum transaction payload.
          Used for: Signing transactions, crucial to safety of users against replay attacks.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/core.cljs

          EIP165 - Standard Interface Detection

          Support: Dependency/Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-165
          Description: Standard interface for contract to answer if it supports other interfaces.
          Used for: Dependency of ENS and EIP721.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip165.cljs

          EIP181 - ENS support for reverse resolution of Ethereum addresses

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-181
          Description: Enable wallets to render reverse resolution of Ethereum addresses.
          Used for: Wallet feature.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/ens.cljs#L86

          EIP191 - Signed Message

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-191
          Description: Contract signature standard, adds an obligatory padding to signed message to differentiate from Ethereum Transaction messages.
          Used for: Dapp support, security, dependency of ERC712.

          EIP627 - Whisper Specification

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-627
          Description: format of Whisper messages within the ÐΞVp2p Wire Protocol.
          Used for: Chat protocol.

          EIP681 - URL Format for Transaction Requests

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-681 Description: A link that pop up a transaction in the wallet.
          Used for: Useful as QR code data for transaction requests, chat transaction requests and for dapp links to transaction requests.
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/eip681.cljs
          Related: Issue #9183: URL Format for Transaction Requests (EIP681) is poorly supported https://github.com/status-im/status-react/pull/9240 https://github.com/status-im/status-react/issues/9238 https://github.com/status-im/status-react/issues/7214 https://github.com/status-im/status-react/issues/7325 https://github.com/status-im/status-react/issues/8150

          EIP712 - Typed Signed Message

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-712
          Description: Standardize types for contract signature, allowing users to easily inspect whats being signed.
          Used for: User experience, security.
          Related: https://github.com/status-im/status-react/issues/5461 https://github.com/status-im/status-react/commit/ba37f7b8d029d3358c7b284f6a2383b9ef9526c9

          EIP721 - Non Fungible Token

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-721
          Description: Enable wallets to use tokens based on smart contracts compliant with this standard.
          Used for: Wallet feature.
          Related: https://github.com/status-im/status-react/issues/8909
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/erc721.cljs https://github.com/status-im/status-react/blob/develop/src/status_im/ethereum/tokens.cljs

          EIP945 - Web 3 QR Code Scanning API

          Support: Full.
          Reference: https://github.com/ethereum/EIPs/issues/945
          Used for: Sharing contactcode, reading transaction requests.
          Related: https://github.com/status-im/status-react/issues/5870

          EIP1102 - Opt-in account exposure

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-1102
          Description: Allow users to opt-in the exposure of their ethereum address to dapps they browse.
          Used for: Privacy, DApp support.
          Related: https://github.com/status-im/status-react/issues/7985

          EIP1193 - Ethereum Provider JavaScript API

          Support: Full.
          Reference: https://eips.ethereum.org/EIPS/eip-1193
          Description: Allows dapps to recognize event changes on wallet.
          Used for: DApp support.
          Related: https://github.com/status-im/status-react/pull/7246

          EIP1577 - contenthash field for ENS

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-1577
          Description: Allows users browse ENS domains using contenthash standard.
          Used for: Browser, DApp support.
          Related: https://github.com/status-im/status-react/issues/6688
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/utils/contenthash.cljs https://github.com/status-im/status-react/blob/develop/test/cljs/status_im/test/utils/contenthash.cljs#L5

          EIP1581 - Non-wallet usage of keys derived from BIP-32 trees

          Support: Partial.
          Reference: https://eips.ethereum.org/EIPS/eip-1581
          Description: Allow wallet to derive keys that are less sensible (non wallet).
          Used for: Security (don’t reuse wallet key) and user experience (don’t request keycard every login).
          Related: https://github.com/status-im/status-react/issues/9088 https://github.com/status-im/status-react/pull/9096
          Sourcecode: https://github.com/status-im/status-react/blob/develop/src/status_im/constants.cljs#L242

          EIP1459 - Node Discovery via DNS

          Support: - Reference: https://eips.ethereum.org/EIPS/eip-1459 Description: Allows the storing and retrieving of nodes through merkle trees stored in TXT records of a domain. Used for: Finding Waku nodes. Related: - Sourcecode: -

          Copyright and related rights waived via CC0.

          diff --git a/stable/index.html b/stable/index.html deleted file mode 100644 index 5f7e7df..0000000 --- a/stable/index.html +++ /dev/null @@ -1 +0,0 @@ - Stable specs - Status Specification Stable specs | Status Specification Link Search Menu Expand Document diff --git a/style-guideline.html b/style-guideline.html index 5c6a5b4..0f7dfb5 100644 --- a/style-guideline.html +++ b/style-guideline.html @@ -1,4 +1,4 @@ - STYLE-GUIDELINE - Status Specification STYLE-GUIDELINE | Status Specification Link Search Menu Expand Document

          Style guidelines for Status client specifications

          Spellcheck

          To run the spellchecker locally, you must install pyspelling.

          It can then be run with the following command:

          pyspelling -c spellcheck.yml
          +     STYLE-GUIDELINE - Status Specification       STYLE-GUIDELINE | Status Specification               Link      Search      Menu      Expand      Document       

          Style guidelines for Status client specifications

          Spellcheck

          To run the spellchecker locally, you must install pyspelling.

          It can then be run with the following command:

          pyspelling -c spellcheck.yml
           

          Words that should be ignored or are unrecognized must be added to the wordlist.

          Markdown Verification

          We use remark to verify our markdown. You can easily run this tool simply by using our npm package:

          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 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.

          Examples: ### Personal pronouns Informal: >In this specification, **we** describe Formal: >This specification describes Informal: >If **you** want to run a Waku node and receive messages from Status clients, it must be properly configured. Formal: >A Waku node must be properly configured to receive messages from Status clients. ### Passive voice Passive voice: >a corresponding confirmation **is broadcast** by one or more peers Active voice: >**one or more peers broadcast** a corresponding confirmation In the case where the object of the sentence needs to be highlighted or given prominence the passive voice is appropriate. However, pay attention to not introduce an ambiguous subject if communicating specific information is your goal. ### Appropriate use of the passive voice >The Batch Acknowledge packet is followed by a keccak256 hash of the envelope's batch data (raw bytes). The subject of the sentence is "a keccak256 hash", but the sentence wants to highlight the Batch Acknowledge. ### Ambiguous subject In many cases sentences written in passive voice may be grammatically correct but hide that the sentence lacks a specified subject. Ambiguous: >A message confirmation **is sent** using Batch Acknowledge Active specific: >**A node sends** a message confirmation using Batch Acknowledge Passive specific: >A message confirmation **is sent by a node** using Batch Acknowledge Notice that the ambiguous sentence infers or omits the subject. Making it unclear what or who performs an action on the object of the sentence. In the example ambiguous sentence it is not stated what or who is sending a message confirmation.