Skip to content
This repository has been archived by the owner on Jun 14, 2024. It is now read-only.

Waku version 0 - initial #28

Merged
merged 55 commits into from
Nov 21, 2019
Merged
Changes from 41 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
fb0b31d
Init with EIP-627
oskarth Nov 5, 2019
dd21983
Header and abstract
oskarth Nov 5, 2019
311ce86
WIP
oskarth Nov 14, 2019
2d6b1c9
Update waku.md
decanus Nov 14, 2019
9accd51
Update waku.md
decanus Nov 14, 2019
0d8c7c1
Inline comments
oskarth Nov 15, 2019
469f1e9
add Dean and toc
oskarth Nov 15, 2019
66950aa
document rlpx subprotocol
oskarth Nov 15, 2019
805a8e2
Rename waku.md to waku/README.md
decanus Nov 15, 2019
701792a
Merge branch 'master' into waku
decanus Nov 15, 2019
5f23fc5
reworded
decanus Nov 16, 2019
c0427ce
light-node (#31)
decanus Nov 18, 2019
d81e6a7
Update README.md
decanus Nov 19, 2019
42f5ff8
Update README.md
decanus Nov 19, 2019
e5a0f61
Update README.md
decanus Nov 19, 2019
a7be9cd
Update README.md
decanus Nov 20, 2019
482045e
Update README.md
decanus Nov 20, 2019
7f9c8f2
Update RLPx subprotocol based on nim-eth changes
oskarth Nov 20, 2019
b8407bb
Add section on backwards compatibility
oskarth Nov 20, 2019
f5e7b90
changelog and todo
oskarth Nov 20, 2019
8d0a4c7
update toc
oskarth Nov 20, 2019
3ed6c0f
update rlpx section
oskarth Nov 20, 2019
e1d11a7
specify rlpx version number
oskarth Nov 20, 2019
a77b54c
add differences shh6 waku 0
oskarth Nov 20, 2019
b8d13f4
generalize light node section to additional capabilities
oskarth Nov 20, 2019
28b0ecc
add mock security considerations section
oskarth Nov 20, 2019
40adc81
mock section of forwards comp
oskarth Nov 20, 2019
beb26b8
bump mini version
oskarth Nov 20, 2019
2ba1043
fix typo
oskarth Nov 20, 2019
5252b36
Update waku/README.md
decanus Nov 20, 2019
5b163ed
Update waku/README.md
decanus Nov 20, 2019
652373e
Update README.md
decanus Nov 20, 2019
e063c36
Update README.md
decanus Nov 20, 2019
fa983db
Update waku/README.md
decanus Nov 20, 2019
b39b93f
Update README.md
decanus Nov 20, 2019
473e2d6
Update README.md
decanus Nov 20, 2019
ab06188
Update README.md
decanus Nov 20, 2019
0995c65
Update waku/README.md
decanus Nov 20, 2019
a6d7d28
Update README.md
decanus Nov 20, 2019
9f5995c
Update README.md
decanus Nov 20, 2019
e624308
Update waku/README.md
decanus Nov 20, 2019
72417d7
Update waku/README.md
decanus Nov 21, 2019
49ff352
Update README.md (#42)
decanus Nov 21, 2019
c285261
Move back to waku.md KISS
oskarth Nov 21, 2019
b08b573
try footnote link
oskarth Nov 21, 2019
2b2ec3f
rlp detail links
oskarth Nov 21, 2019
36b048c
add ABNF spec
oskarth Nov 21, 2019
01bc9f7
moar abnf, and remove superfluous data format descriptions
oskarth Nov 21, 2019
cf12ce0
modify abstract and motivation
oskarth Nov 21, 2019
65cd30a
abnf whisper envelope
oskarth Nov 21, 2019
fe1931d
move security consider
oskarth Nov 21, 2019
af85722
clarify duplication
oskarth Nov 21, 2019
66ba199
some backwards compatibility notes and move things a bit
oskarth Nov 21, 2019
da24243
version 0.1.0 prepare for merge; toc; ack section
oskarth Nov 21, 2019
35eff0e
tweak acks
oskarth Nov 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
310 changes: 310 additions & 0 deletions waku/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
# Waku Whisper Specification

> Version 0.0.5 (Draft)
>
> Authors: Oskar Thorén oskar@status.im, Dean Eigenmann dean@status.im

## Table of Contents

- [Abstract](#abstract)
- [Motivation](#motivation)
- [Specification](#specification)
- [Use of RLPx transport protocol](#use-of-rlpx-transport-protocol)
- [Packet Codes](#packet-codes)
- [Packet Format and Usage](#packet-format-and-usage)
- [Whisper Envelope](#whisper-envelope)
- [Contents of Data Field of the Message (Optional)](#contents-of-data-field-of-the-message-optional)
- [Payload Encryption](#payload-encryption)
- [Light node](#light-node)
- [Rationale](#rationale)
- [Backwards Compatibility](#backwards-compatibility)
- [WakuWhisper bridging](#wakuwhisper-bridging)
- [Forwards Compatibility](#forwards-compatibility)
- [Security Considerations](#security-considerations)
- [Implementation](#implementation)
- [Changelog](#changelog)
- [Differences between shh/6 waku/0](#differences-between-shh6-waku0)
- [Copyright](#copyright)

## Abstract

This specification describes the format of Waku messages within the ÐΞVp2p Wire Protocol. This spec substitutes [EIP- 627](https://eips.ethereum.org/EIPS/eip-627). Waku is a fork of the original Whisper protocol that enables better scalability and offline messaging, at the cost of some metadata protection guarantees. It does this through (a) light node support (b) mailserver (c) waku mode and (d) basic rate limiting.
oskarth marked this conversation as resolved.
Show resolved Hide resolved

## Motivation

<!-- This should be the motivation of Waku rather than the motivation of this spec: aka to enable scalability etc. -->

It is necessary to 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.
oskarth marked this conversation as resolved.
Show resolved Hide resolved

## Specification

### Use of RLPx transport protocol

All Waku messages are sent as devp2p [RLPx transport protocol, version 5](https://github.com/ethereum/devp2p/blob/master/rlpx.md) packets. These packets MUST be RLP-encoded arrays of data containing two objects: packet code followed by another object (whose type depends on the packet code).

Waku nodes that do not support a particular packet code MUST ignore the packet without generating any error.

Waku is a RLPx subprotocol called `waku` with version `0`. The version number corresponds to the major version in the header spec.

### Packet Codes

<!-- Packet code not clear -->

The message codes reserved for Waku protocol: 0 - 127.

<!-- Is this a MUST or rather a SHOULD -->

Messages with unknown codes MUST be ignored, for forward compatibility of future versions.
decanus marked this conversation as resolved.
Show resolved Hide resolved

The Waku sub-protocol MUST support the following packet codes:

| Name | Int Value |
|----------------------------|-----------|
| Status | 0 |
| Messages | 1 |
| PoW Requirement | 2 |
| Bloom Filter | 3 |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need one more to broadcast rate limit settings if this is the way to go. Also, there should be an additional code for message confirmations. Currently it is 11 and 12 but 125 makes more sense IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adambabik can you please provide the additional message codes? Which are optional?



The following message codes are optional, but they are reserved for specific purpose.

| Name | Int Value |
|----------------------------|-----------|
| P2P Request | 126 |
| P2P Message | 127 |

### Packet Format and Usage
oskarth marked this conversation as resolved.
Show resolved Hide resolved

**Status** [`0`, [`version`, `pow_requirement`, `bloom_filter`, `light_node`]]

<!-- @todo maybe make a table or something -->

This packet contains two objects: integer message code (0x00) followed by a list of values:

| Field | Type |
| ----- | ---- |
| `version` | integer |
| `pow requirement` | IEEE 754 binary representation of 64-bit floating point number |
| `bloom filter` | byte array |
| `light node` | bool |

**Note**: The bloom filter paramenter is optional; if it is missing or nil, the node is considered to be full node (i.e. accepts all messages). The format of PoW and bloom filter please see below (message codes 2 and 3).

Status message should be sent after the RLPx handshake and prior to any other messages.

When a node does not receive the status message from a peer, before a configurable timeout, it MUST disconnect from that peer.

**Messages** [`1`, `whisper_envelopes`]

This packet contains two objects: message code (0x01) followed by a list (possibly empty) of Whisper Envelopes.
oskarth marked this conversation as resolved.
Show resolved Hide resolved

This packet is used for sending the standard Whisper envelopes.

**PoW Requirement** [`2`, `PoW`]

This packet contains two objects: message code (0x02) followed by the value of PoW. This value is the IEEE 754 binary representation of 64-bit floating point number. Values of qNAN, sNAN, INF and -INF are not allowed. Negative values are also not allowed.

This packet is used by Whisper nodes for dynamic adjustment of their individual PoW requirements. Recipient of this message should no longer deliver the sender messages with PoW lower than specified in this message.

PoW is defined as average number of iterations, required to find the current BestBit (the number of leading zero bits in the hash), divided by message size and TTL:

PoW = (2**BestBit) / (size * TTL)

PoW calculation:

fn short_rlp(envelope) = rlp of envelope, excluding env_nonce field.
fn pow_hash(envelope, env_nonce) = sha3(short_rlp(envelope) ++ env_nonce)
fn pow(pow_hash, size, ttl) = 2**leading_zeros(pow_hash) / (size * ttl)

where size is the size of the full RLP-encoded envelope.
decanus marked this conversation as resolved.
Show resolved Hide resolved

**Bloom Filter** [`3`, `bytes`]

This packet contains two objects: integer message code (0x03) followed by a byte array of arbitrary size.

This packet is used by Whisper nodes for sharing their interest in messages with specific topics.

The Bloom filter is used to identify a number of topics to a peer without compromising (too much) privacy over precisely what topics are of interest. Precise control over the information content (and thus efficiency of the filter) may be maintained through the addition of bits.

Blooms are formed by the bitwise OR operation on a number of bloomed topics. The bloom function takes the topic and projects them onto a 512-bit slice. At most, three bits are marked for each bloomed topic.

The projection function is defined as a mapping from a 4-byte slice S to a 512-bit slice D; for ease of explanation, S will dereference to bytes, whereas D will dereference to bits.

LET D[*] = 0
FOREACH i IN { 0, 1, 2 } DO
LET n = S[i]
IF S[3] & (2 ** i) THEN n += 256
D[n] = 1
END FOR


OPTIONAL

**P2P Request** [`126`, `whisper_envelope`]

This packet contains two objects: integer message code (0x7E) followed by a single Whisper Envelope.

This packet is used for sending Dapp-level peer-to-peer requests, e.g. Whisper Mail Client requesting old messages from the Whisper Mail Server.

**P2P Message** [`127`, `whisper_envelope`]

This packet contains two objects: integer message code (0x7F) followed by a single Whisper Envelope.

This packet is used for sending the peer-to-peer messages, which are not supposed to be forwarded any further. E.g. it might be used by the Whisper Mail Server for delivery of old (expired) messages, which is otherwise not allowed.


### Whisper Envelope

Envelopes are RLP-encoded structures of the following format:

```
[ Expiry, TTL, Topic, Data, Nonce ]
```

| Field | Type |
|-|-|
| Expiry | 4 bytes (UNIX time in seconds) |
| TTL | 4 bytes (time-to-live in seconds) |
| Topic | 4 bytes of arbitrary data |
| Data | byte array of arbitrary size (contains encrypted message) |
| Nonce | 8 bytes of arbitrary data (used for PoW calculation) |

### Contents of Data Field of the Message (Optional)

This section outlines the optional description of Data Field to set up an example. Later it may be moved to a separate EIP.

It is only relevant if you want to decrypt the incoming message, but if you only want to send a message, any other format would be perfectly valid and must be forwarded to the peers.

Data field contains encrypted message of the Envelope. In case of symmetric encryption, it also contains appended Salt (a.k.a. AES Nonce, 12 bytes). Plaintext (unencrypted) payload consists of the following concatenated fields: flags, auxiliary field, payload, padding and signature (in this sequence).

flags: 1 byte; first two bits contain the size of auxiliary field, third bit indicates whether the signature is present.

auxiliary field: up to 4 bytes; contains the size of payload.

payload: byte array of arbitrary size (may be zero).

padding: byte array of arbitrary size (may be zero).

signature: 65 bytes, if present.

salt: 12 bytes, if present (in case of symmetric encryption).

Those unable to decrypt the message data are also unable to access the signature. The signature, if provided, is the ECDSA signature of the Keccak-256 hash of the unencrypted data using the secret key of the originator identity. The signature is serialised as the concatenation of the `R`, `S` and `V` parameters of the SECP-256k1 ECDSA signature, in that order. `R` and `S` are both big-endian encoded, fixed-width 256-bit unsigned. `V` is an 8-bit big-endian encoded, non-normalised and should be either 27 or 28.

The padding field was introduced in order to align the message size, since message size alone might reveal important metainformation. Padding can be arbitrary size. However, it is recommended that the size of Data Field (excuding the Salt) before encryption (i.e. plain text) should be factor of 256 bytes.

### Payload Encryption

Asymmetric encryption uses the standard Elliptic Curve Integrated Encryption Scheme with SECP-256k1 public key.

Symmetric encryption uses AES GCM algorithm with random 96-bit nonce.

## Additional capabilities

Waku supports multiple capabilities. These include light node, rate limting, mailserver (client and server) and bridging of traffic. Here we list these capabilities, how they are identified, what properties they have and what invariants they must maintain.

### Light node

The rationale for light nodes is to allow for interaction with waku on resource restricted devices as bandwidth can often be an issue.

Light nodes MUST NOT forward any incoming messages, they MUST only send their own messages. When light nodes happen to connect to each other, they SHOULD disconnect. As this would result in messages being dropped between the two.

Light nodes are identified by the `light_node` value in the status message.

<!-- TODO: Add details on handshake -- >

**Security consideration**:
Running a node as a light node mode impacts privacy due to the fact that it becomes identifiable what nodes care about if they aren't relaying traffic.
oskarth marked this conversation as resolved.
Show resolved Hide resolved

<!-- TODO: Consider moving all security considerations to end section of document -->

### Mailserver and client

<!-- TODO: Clean up vocabulary, is it mailserver and mailserver client? mailclient? mailserver node? historynode? etc -->
oskarth marked this conversation as resolved.
Show resolved Hide resolved

## Rationale

Packet codes 0x00 and 0x01 are already used in all Whisper versions.

Packet code 0x02 will be necessary for the future development of Whisper. It will provide possiblitity to adjust the PoW requirement in real time. It is better to allow the network to govern itself, rather than hardcode any specific value for minimal PoW requirement.

Packet code 0x03 will be necessary for scalability of the network. In case of too much traffic, the nodes will be able to request and receive only the messages they are interested in.

Packet codes 0x7E and 0x7F may be used to implement Whisper Mail Server and Client. Without P2P messages it would be impossible to deliver the old messages, since they will be recognized as expired, and the peer will be disconnected for violating the Whisper protocol. They might be useful for other purposes when it is not possible to spend time on PoW, e.g. if a stock exchange will want to provide live feed about the latest trades.

## Backwards Compatibility

This EIP is backward compatible with Whisper version 6. Any client which does not implement certain packet codes should gracefully ignore the packets with those codes. This will ensure the forward compatibility.

### WakuWhisper bridging

`waku/0` and `shh/6` are different DevP2P subprotocols. In order to achieve backwards compatibility, bridging is required. It works as follows.

**Roles:**
- Waku client A, only Waku capability
- Whisper client B, only Whisper capability
- WakuWhisper bridge C, both Waku and Whisper capability

**Flow:**
1. A posts message; B posts message.
2. C picks up message from A and B and relays them both to Waku and Whisper.
3. A receives message on Waku; B on Whisper.

**Note**: This flow means if another bridge C1 is active, we might get duplicate relaying for a message. I.e. Whisper(<>Waku<>Whisper)<>Waku, A-C1-C2-B. Theoretically this bridging chain can get as long as TTL permits.
oskarth marked this conversation as resolved.
Show resolved Hide resolved

## Forwards Compatibility

It is desirable to maintain forward compatibility between `waku/0` and future version of waku. Here we outline some concerns and strategy for this.

<!-- TODO: Think about how to maintain forwards capability for waku/v0 -> v1 -> v2, etc. -->
oskarth marked this conversation as resolved.
Show resolved Hide resolved
<!-- Example user story: changing version number to 1; moving to libp2p; changing routing to PSS style; remove PoW; replacing PoW with zkSNARKs; adding packet codes for rate limit / accounting for resources feedback; additional disconnect features -->
oskarth marked this conversation as resolved.
Show resolved Hide resolved

<!-- TODO: Right now we have

if m.protocolVersion == wakuVersion:
debug "Waku peer", peer, wakuVersion
else:
raise newException(UselessPeerError, "Incompatible Waku version")

Is this what we want? Decide!
-->


## Security considerations

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

<!-- TODO: elaborate on security considerations -->

## Implementation

The golang implementation of Whisper (v.6) already uses packet codes 0x00 - 0x03. Parity's implementation of v.6 will also use codes 0x00 - 0x03. Codes 0x7E and 0x7F are reserved, but still unused and left for custom implementation of Whisper Mail Server.

<!-- TODO(Dean): Break out into Status spec and remove this section -->

## Changelog

| Version | Comment |
| :-----: | ------- |
| 0.0.5 (current) | [WIP] Initial Release |

<!-- TODO: Start counting at 0.1, which is when this PR is merged -->

### Differences between shh/6 waku/0

Summary of main differences between this spec and Whisper v6, as described in [EIP-627](https://eips.ethereum.org/EIPS/eip-627):

- RLPx subprotocol is changed from `shh/6` to `waku/0`
- Light node capability
- Whisper Mail Server and Whisper Mail Client implemented

<!-- TODO: Document further differences with Whisper v6 -->

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

<!-- TODO: Document recommendations for mobile nodes node --->
<!-- TODO: Document spam resistance in practice, rate limiting -->
<!-- TODO: Document accounting for resources, with mention of later settlement -->
<!-- TODO: Consider adding roadmap, or link to -->