github.com/status-im/status-go@v1.1.0/wakuv2/README.md (about)

     1  # `waku`
     2  
     3  ## Table of contents
     4  
     5  - [What is Waku?](#what-is-waku)
     6  - [Waku versioning](#waku-versioning)
     7  - [What does this package do?](#what-does-this-package-do)
     8  - [Waku package files](#waku-package-files)
     9  
    10  ## What is Waku?
    11  
    12  Waku is a communication protocol for sending messages between Dapps. Waku is a fork of the [Ethereum Whisper subprotocol](https://github.com/ethereum/wiki/wiki/Whisper), although not directly compatible with Whisper, both Waku and Whisper subprotocols can communicate [via bridging](https://github.com/vacp2p/specs/blob/master/specs/waku/waku-1.md#backwards-compatibility).
    13  
    14  Waku was [created to solve scaling issues with Whisper](https://discuss.status.im/t/fixing-whisper-for-great-profit/1419) and [currently diverges](https://github.com/vacp2p/specs/blob/master/specs/waku/waku-1.md#differences-between-shh6-and-waku1) from Whisper in the following ways:
    15  
    16  - RLPx subprotocol is changed from `shh/6` to `waku/1`.
    17  - Light node capability is added.*
    18  - Optional rate limiting is added.
    19  - Status packet has following additional parameters: light-node, confirmations-enabled and rate-limits
    20  - Mail Server and Mail Client functionality is now part of the specification.
    21  - P2P Message packet contains a list of envelopes instead of a single envelope.
    22  
    23  *As per [vacp2p/specs#117](https://github.com/vacp2p/specs/pull/117) Waku de jure introduced light nodes as far as updates to the written Whisper specifications. Though the de facto case is that the `go-ethereum` Whisper implementation had [already implemented light nodes](https://github.com/ethereum/go-ethereum/blob/510b6f90db406b697610fe0ff2eee66d173673b2/whisper/whisperv6/whisper.go#L291) and weren't a new feature in code.
    24  
    25  Although `status-go`'s Waku light node functionality is a direct fork of `go-ethereum`'s Whisper light node functionality, technically, as far as specifications are concerned, light nodes are considered a new feature introduced in Waku.  
    26  
    27  ## Waku versioning
    28  
    29  This package follows a versioning pattern that makes clean separation between breaking versions. As [detailed in the PR](https://github.com/status-im/status-go/pull/1947#issue-407073908) that introduced this strategy to the package.
    30  
    31  >... the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore.
    32  >
    33  >This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by whisper in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk.
    34  
    35  Familiarise yourself with the [Spec-ulation Keynote by Rich Hickey](https://www.youtube.com/watch?v=oyLBGkS5ICk), if you wish to more deeply understand the rationale for this versioning implementation. 
    36  
    37  This means that breaking changes will necessitate a new protocol version and a new version sub-package. The packages follow the naming convention of `v*` where `*` represents the major / breaking version number of the protocol.
    38  
    39  Currently the package has the following version sub-packages:
    40  
    41  - [version 0 - `v0`](./v0)
    42  - [version 1 - `v1`](./v1)
    43  
    44  ## What does this package do? 
    45  
    46  The basic function of this package is to implement the [waku specifications](https://github.com/vacp2p/specs/blob/master/specs/waku/waku-1.md), and provide the `status-go` binary with the ability to send and receive messages via Waku.
    47  
    48  ## Waku package files
    49  
    50    - [waku.go](#wakugo)
    51    - [api.go](#apigo)
    52    - [config.go](#configgo)
    53    - [mailserver.go](#mailservergo)
    54    - [common](#common)
    55      - [bloomfilter.go](#bloomfiltergo)
    56      - [const.go](#constgo)
    57      - [envelope.go](#envelopego)
    58      - [errors.go](#errorsgo)
    59      - [events.go](#eventsgo)
    60      - [filter.go](#filtergo)
    61      - [helpers.go](#helpersgo)
    62      - [message.go](#messagego)
    63      - [metrics.go](#metricsgo)
    64      - [protocol.go](#protocolgo)
    65      - [rate_limiter.go](#rate_limitergo)
    66      - [topic.go](#topicgo)
    67    - [Versioned](#versioned)
    68       - [const.go](#version-constgo)
    69       - [init.go](#version-initgo)
    70       - [message.go](#version-messagego)
    71       - [peer.go](#version-peergo)
    72       - [status_options.go](#version-status_optionsgo)
    73  
    74  ## Root
    75  
    76  ### `waku.go`
    77  
    78  [`waku.go`](./waku.go) serves as the main entry point for the package and where the main `Waku{}` struct lives.
    79  
    80  ---
    81  
    82  ### `api.go`
    83  
    84  [`api.go`](./api.go) is home to the `PublicWakuAPI{}` struct which provides the waku RPC service that can be used publicly without security implications.
    85  
    86  `PublicWakuAPI{}` wraps the main `Waku{}`, making the `Waku{}` functionality suitable for external consumption.
    87  
    88  #### Consumption
    89  
    90  `PublicWakuAPI{}` is wrapped by `eth-node\bridge\geth.gethPublicWakuAPIWrapper{}`, which is initialised via `eth-node\bridge\geth.NewGethPublicWakuAPIWrapper()` and exposed via `gethWakuWrapper.PublicWakuAPI()` and is finally consumed by wider parts of the application.
    91  
    92  #### Notes
    93  
    94  It is worth noting that each function of `PublicWakuAPI{}` received an unused `context.Context` parameter. This is originally passed in way higher up the food-chain and without significant refactoring is not a simple thing to remove / change. Mobile bindings depend on the ability to pass in a context.
    95  
    96  ---
    97  
    98  ### `config.go`
    99  
   100  [`config.go`](./config.go) is home to the `Config{}` struct and the declaration of `DefaultConfig`.
   101  
   102  `Config{}` is used to initialise the settings of an instantiated `Waku{}`. `waku.New()` creates a new instance of a `Waku{}` and takes a `Config{}` as a parameter, if nil is passed instead of an instance of `Config{}`, `DefaultConfig` is used. 
   103  
   104  #### Configuration values
   105  
   106  |Name                      |Type     |Description|
   107  |--------------------------|---------|---|
   108  |`MaxMessageSize`          |`uint32` |Sets the maximum size of a waku message in bytes|
   109  |`MinimumAcceptedPoW`      |`float64`|Sets the minimum amount of work a message needs to have to be accepted by the waku node|
   110  |`BloomFilterMode`         |`bool`   |When true, the waku node only matches against bloom filter|
   111  |`LightClient`             |`bool`   |When true, the waku node does not forward messages|
   112  |`FullNode`                |`bool`   |When true, the waku node forwards all messages|
   113  |`RestrictLightClientsConn`|`bool`   |When true, the waku node does not accept light clients as peers if it is a light client itself|
   114  |`EnableConfirmations`     |`bool`   |When true, sends message confirmations|
   115  
   116  #### Default
   117  
   118  The default configuration for a `status-go` Waku node is:
   119  
   120  	MaxMessageSize           : 1Mb
   121  	MinimumAcceptedPoW       : 0.2
   122  	RestrictLightClientsConn : true
   123  
   124  ---
   125  
   126  ### `mailserver.go`
   127  
   128  [`mailserver.go`](./mailserver.go) is home to `MailServer` interface, which is implemented by `mailserver.WakuMailServer{}` found in the package file [`mailserver/mailserver.go`](../mailserver/mailserver.go). `MailServer` represents a mail server, capable of receiving and archiving messages for subsequent delivery to the peers.
   129  
   130  Additionally this package is home to `MailServerResponse{}` which represents the response payload sent by the mail-server. `MailServerResponse{}` is ultimately initialised by `CreateMailServerEvent()`, which is tied to the main `Waku{}` via the `Waku.OnP2PRequestCompleted()` function. This is ultimately accessed via the `Peer.Run()` function and is made available outside of the package with the `waku.HandlePeer()` function via `Waku.protocol.Run := waku.HandlePeer`. 
   131  
   132  ---
   133  
   134  ## Common
   135  
   136  ### `bloomfilter.go`
   137  
   138  [`bloomfilter.go`](./common/bloomfilter.go) holds a few bloomfilter specific functions.
   139  
   140  ---
   141  
   142  ### `const.go`
   143  
   144  [`const.go`](./common/const.go), originally a hangover from the [`go-ethereum` `whisperv6/doc.go` package file](https://github.com/ethereum/go-ethereum/blob/master/whisper/whisperv6/doc.go) later [refactored](https://github.com/status-im/status-go/pull/1950), is home to the common Waku constants.
   145  
   146  #### Notes
   147  
   148  Versions also have version specific `const.go` files.
   149  
   150  ---
   151  
   152  ### `envelope.go`
   153  
   154  [`envelope.go`](./common/envelope.go) is home to the `Evelope{}` and `EnvelopeError{}` structs. `Envelope{}` is used as the data packet in which message data is sent through the Waku network.
   155  
   156  `Envelope{}` is accessed via the initialisation function `NewEnvelope()`, which is exclusively consumed by `Message.Wrap()` that prepares a message to be sent via Waku. 
   157  
   158  ---
   159  
   160  ### `errors.go`
   161  
   162  [`errors.go`](./common/errors.go) holds generic package errors.
   163  
   164  ---
   165  
   166  ### `events.go`
   167  
   168  [`events.go`](./common/events.go) handles data related to Waku events. This file contains string type `const`s that identify known Waku events.
   169  
   170  Additionally, the file contains `EnvelopeEvent{}`, which serves as a representation of events created by envelopes. `EnvelopeEvent{}`s are initialised exclusively within the `waku` package.  
   171  
   172  --- 
   173  
   174  ### `filter.go`
   175  
   176  [`filter.go`](./common/filter.go) is home to `Filter{}` which represents a waku filter.
   177  
   178  #### Usage
   179  
   180  A `status-go` node will install / register filters through RPC calls from a client (eg `status-mobile`). The basic implementation of a filter requires at least 2 things:
   181  
   182  1) An encryption key, example "`superSafeEncryptionKey`"
   183  2) A 4 byte topic (`TopicType`), example "`0x1234`"
   184  
   185  The node will install the filter `[0x1234][{"superSafeEncryptionKey"}]` on an instance of `Filters{}` and will notify its peers of this event
   186  
   187  When a node receives an envelope it will attempt to match the topics against the installed filters, and then try to decrypt the envelope if the topic matches.
   188  
   189  For example, if a node receives an envelope with topic `0x1234`, the node will try to use the installed filter key `superSafeEncryptionKey` to decrypt the message. On success the node passes the decrypted message to the client.
   190  
   191  In addition to the basic example above `Filter{}` allows for richer filtering:
   192  
   193  |Field Name  |Type               |Description                                |
   194  |------------|-------------------|-------------------------------------------|
   195  |`Src`       |`*ecdsa.PublicKey` |Sender of the message. *Currently not used*|
   196  |`KeyAsym`   |`*ecdsa.PrivateKey`|Private Key of recipient                   |
   197  |`KeySym`    |`[]byte`           |Key associated with the Topic              |
   198  |`Topics`    |`[][]byte`         |Topics to filter messages with             |
   199  |`PoW`       |`float64`          |Proof of work as [described in the Waku specs](https://github.com/vacp2p/specs/blob/master/specs/waku/waku-1.md#pow-requirement-update) .<br/><br/>**Note:** *In `status-mobile` each client listens to the topic hash(pk), if a client wants to send a message to hash(pk1) they will also need to listen the hash(pk1) topic. However if the client doesn't want to receive envelopes for topic hash(pk1), the client may set the PoW to 1 so that all envelopes for topic hash(pk1) are discarded.*|
   200  |`AllowP2P`  |`bool`             |Indicates whether this filter is interested in direct peer-to-peer messages.<br/><br/>**Note:** *Typically set to true, we always want to receive P2P envelopes on a filter from trusted peers*|
   201  |`SymKeyHash`|`common.Hash`      |The Keccak256Hash of the symmetric key, needed for optimization|   
   202  
   203  **Waku / Whisper divergence**
   204  
   205  Whisper, will process all the installed filters that the node has, and build a `BloomFilter` from all the topics of each installed filter (i.e. `func ToBloomFilter(topics []TopicType) []byte { ... }`). When a peer receives this BloomFilter, it will match the topic on each envelope that they receive against the BloomFilter, if it matches, it will forward this to the peer.
   206  
   207  Waku, by default, does not send a BloomFilter, instead sends the topic in a clear array of `[]TopicType`. This is an improvement on Whisper's usage as a BloomFilter may include false positives, which increase bandwidth usage. In contrast, clear topics are matched exactly and therefore don't create redundant bandwidth usage.
   208  
   209  ---
   210  
   211  ### `helpers.go`
   212  
   213  [`helpers.go`](./common/helpers.go) holds the package's generic functions.
   214  
   215  ---
   216  
   217  ### `message.go`
   218  
   219  [`message.go`](./common/message.go) is home to all message related functionality and contains a number of structs:
   220  
   221  |Name|Description|
   222  |---|---|
   223  |`MessageParams{}`|Specifies the exact way a message should be wrapped into an Envelope|
   224  |`sentMessage{}`|Represents an end-user data packet to transmit through the Waku protocol. These are wrapped into Envelopes that need not be understood by intermediate nodes, just forwarded.|
   225  |`ReceivedMessage{}`|Represents a data packet to be received through the Waku protocol and successfully decrypted.|
   226  |`MessagesRequest{}`|Contains details of a request for historic messages.|
   227  |`MessagesResponse{}`|Represents a request response sent after processing batch of envelopes.|
   228  |`MessageStore` `interface`|Implemented by `MemoryMessageStore{}`|
   229  |`MemoryMessageStore{}`|Represents messages stored in a memory hash table.|
   230  
   231  ---
   232  
   233  ### `metrics.go`
   234  
   235  [`metrics.go`](./common/metrics.go) is home to [Prometheus](https://prometheus.io/) metric hooks, for counting a range of Waku related metrics.
   236  
   237  ---
   238  
   239  ### `protocol.go`
   240  
   241  [`protocol.go`](./common/protocol.go) houses the `Peer` and `WakuHost` interfaces.
   242  
   243  `Peer` represents a remote Waku client with which the local host waku instance exchanges data / messages. 
   244  
   245  `WakuHost` is the local instance of waku, which both interacts with remote clients (peers) and local clients (like `status-mobile`, via a RPC API).
   246  
   247  ---
   248  
   249  ### `rate_limiter.go`
   250  
   251  [`rate_limiter.go`](./common/rate_limiter.go) was introduced as an improvement to Whisper allowing Waku nodes to limit the rate at which data is transferred. These limits are defined by the `RateLimits{}` which allows nodes to limit the following:
   252  
   253  |Limit Type|Description|
   254  |---|---|
   255  |`IPLimits`|Messages per second from a single IP (default 0, no limits)|
   256  |`PeerIDLimits`|Messages per second from a single peer ID (default 0, no limits)|
   257  |`TopicLimits`|Messages per second from a single topic (default 0, no limits)|
   258  
   259  In addition to the `RateLimits{}` this file also contains the following interfaces and structs.
   260  
   261  |Name|Description|
   262  |---|---|
   263  |`RateLimiterPeer` `interface`|Represents a `Peer{}` that is capable of being rate limited|
   264  |`RateLimiterHandler` `interface`|Represents handler functionality for a Rate Limiter in the cases of exceeding a peer limit and exceeding an IP limit|
   265  |`MetricsRateLimiterHandler{}`|Implements `RateLimiterHandler`, represents a handler for reporting rate limit Exceed data to the metrics collection service (currently prometheus)|
   266  |`DropPeerRateLimiterHandler{}`|Implements `RateLimiterHandler`, represents a handler that introduces Tolerance to the number of Peer connections before Limit Exceeded errors are returned.|
   267  |`RateLimits{}`|Represents rate limit settings exchanged using rateLimitingCode packet or in the handshake.|
   268  |`PeerRateLimiterConfig{}`|Represents configurations for initialising a PeerRateLimiter|
   269  |`PeerRateLimiter{}`|Represents a rate limiter that limits communication between Peers|
   270  
   271  The default PeerRateLimiterConfig is:
   272  
   273  ```text
   274  LimitPerSecIP:      10,
   275  LimitPerSecPeerID:  5,
   276  WhitelistedIPs:     nil,
   277  WhitelistedPeerIDs: nil,
   278  ```
   279  
   280  ---
   281  
   282  ### `topic.go`
   283  
   284  [`topic.go`](./common/topic.go) houses the `TopicType` type.
   285  
   286  `TopicType` represents a cryptographically secure, probabilistic partial classification of a message, determined as the first (leftmost) 4 bytes of the SHA3 hash of some arbitrary data given by the original author of a message.
   287  
   288  Topics are used to filter incoming messages that the host's user has registered interest in. For further details on filtering see [filter.go](#filtergo).
   289  
   290  ---
   291  
   292  ## Versioned
   293  
   294  For details about the divergence between versions please consult the `README`s of each version package.
   295  
   296  - [version 0](./v0)
   297  - [version 1](./v1)
   298  
   299  ---
   300  
   301  ### Version `const.go`
   302  
   303  `const.go` is home to the version sub-package's `const`s. These constants are version dependant and, as expected, may change from version to version.
   304  
   305  ---
   306  
   307  ### Version `init.go`
   308  
   309  `init.go` is home to the version sub-package's initialisation, and is used to initialise struct based variables at runtime. 
   310  
   311  ---
   312  
   313  ### Version `message.go`
   314  
   315  `message.go` is home to the `MultiVersionResponse{}` and `Version1MessageResponse{}` structs, both of which are exclusively consumed by the version subpackage's `Peer{}`.
   316  
   317  Both of these structs are used for handling Waku message responses, also known as message confirmations.
   318  
   319  `Version1MessageResponse{}` is used for sending message responses. `MultiVersionResponse{}` is used for handling incoming message responses. 
   320  
   321  #### Usage
   322  
   323  Message confirmations are used to inform a user, via the UI, that a message has been sent.
   324  Initially the message is marked as "Pending" and eventually as "Sent".
   325  
   326  In order to trigger the message state transition from "pending" to "sent",
   327  Waku uses `MessageResponse{}`. Each peer on receiving a message will send back a `MessageResponse`,
   328  see the [`NewMessagesResponse()` function](https://github.com/status-im/status-go/blob/4d00656c41909ccdd80a8a77a0982bd66f74d29e/waku/v1/message.go#L31).
   329  
   330  The Waku host checks that the peer is a mailserver and if this mailserver was selected by the user,
   331  if so the message will be marked as "Sent" in the UI.
   332  
   333  For further details [read the Waku specification section](https://github.com/status-im/specs/blob/master/docs/stable/3-whisper-usage.md#message-confirmations) on the subject.
   334  
   335  #### Notes
   336  
   337  Versioning at the `MessageResponse` level (see the struct Version field) should be phased out and defer to the subpackage's version number. Consider removal once we decide to move to a new major Waku version (i.e. `waku/2`).
   338  
   339  ---
   340  
   341  ### Version `peer.go`
   342  
   343  `peer.go` holds the version's sub-package `Peer{}` implementation of the `common.Peer` interface. 
   344  
   345  ---
   346  
   347  ### Version `status_options.go`
   348  
   349  `status_options.go` holds the version's sub-package `StatusOptions{}` which implements the `ethereum/go-ethereum/rlp` `Decoder` and `Encoder` interfaces.
   350  
   351  `StatusOptions` defines additional information shared between peers during the handshake. There might be more options provided than fields in `StatusOptions`, and as per the specs, should be ignored during deserialisation to stay forward compatible. In the case of RLP, options should be serialised to an array of tuples where the first item is a field name and the second is a RLP-serialised value.
   352  
   353  For further details on RLP see:
   354  - https://github.com/ethereum/wiki/wiki/RLP
   355  - https://specs.vac.dev/specs/waku/waku.html#use-of-rlpx-transport-protocol