From f840ceb0bdff673be54cabfec4f4c3a81d7d115e Mon Sep 17 00:00:00 2001 From: "fryorcraken.eth" Date: Tue, 8 Nov 2022 10:42:05 +1100 Subject: [PATCH] Squashed commit of the following: commit dd5a32197457cdcb0c09f838cb05c5b5a3109b81 Author: fryorcraken.eth Date: Tue Nov 8 10:28:31 2022 +1100 Remove unneeded sentence commit af1a5415cd21b6a9d424ebe267a83944fbb84ff4 Author: fryorcraken.eth Date: Tue Nov 8 10:26:05 2022 +1100 Fix typo commit a51d98c64925c0d87695c8f49cbdb39d1461f13d Author: fryorcraken.eth Date: Tue Nov 8 10:23:26 2022 +1100 Fix spelling/terminology commit 9bab3692854f510c429582c17ae41b6d5d753e44 Author: danisharora099 Date: Tue Nov 8 00:45:58 2022 +0530 fix: build commit 3cb05f0115f5c84a8aab5f7727a86384c1b68d8f Author: danisharora099 Date: Mon Nov 7 19:39:54 2022 +0530 resolve conflict commit 7f2fa8969ca320070e097594cec3d38994409114 Merge: 726a397 d1c93ec Author: danisharora099 Date: Mon Nov 7 19:39:47 2022 +0530 Merge remote-tracking branch 'refs/remotes/origin/danisharora/update-docs' into danisharora/update-docs commit 726a397f04fdc2380f70618532839a7cc31ff68d Author: danisharora099 Date: Mon Nov 7 19:37:07 2022 +0530 address comments and clean up commit d1c93ec03e83fef26b96ceb7c990f450646fff9e Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:34:35 2022 +0530 Update docs/Guide/01-Prerequisites/1.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 7e86d1a08ba7dff2524e37f2e0073966705c55a2 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:34:25 2022 +0530 Update docs/Guide/01-Prerequisites/1.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit d94bd4a00c2fa27b696d20e88e0ac05459733beb Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:34:09 2022 +0530 Update docs/Guide/01-Prerequisites/1.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 19d727518fff2f28cfdf29e05cbbd7bfe4a4bab4 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:33:58 2022 +0530 Update docs/Concepts/7.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 3570c2ff6446b0cd1dea48a214f9ce8b5ca6a1de Author: danisharora099 Date: Mon Nov 7 19:32:04 2022 +0530 rm: section commit 576b5c1c2c2b034dfd17a192f417a9c89e968dbe Author: danisharora099 Date: Mon Nov 7 19:31:06 2022 +0530 rm: protocol identifiers commit 5a0ea01bdbc38ac54b0f3824c8ed3eb9feb609d4 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:26:03 2022 +0530 Update docs/Concepts/1.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit b60b0abaebf0b553c4eb8041b5da83aac282c6a6 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:25:39 2022 +0530 Update docs/About/7.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit c280e4d6df1d7a16e884e13c0319bdecad833db7 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:25:24 2022 +0530 Update docs/About/6.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit ded38b4d795b02c4ca4d8dfe4a0c588b0b68bfcc Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:21:57 2022 +0530 Update docs/About/4.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 85f6161aeefc4591a59a2f424a7f39ecb7d8c74c Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:21:46 2022 +0530 Update docs/About/4.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 72c0cb9d28ff4b030ebd874b0650b67182bbd015 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:20:31 2022 +0530 Update docs/About/3.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 6e4a067fe5b352789a45bb19b65e2168e655c77f Author: danisharora099 Date: Mon Nov 7 19:20:20 2022 +0530 fix: gitignore commit b2871014aaeabf2ca6d3f7cdf5da89662f8e81a3 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Mon Nov 7 19:16:45 2022 +0530 Update docs/About/7.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 66b7add730064730ad26610eebaeec672a1619e2 Author: danisharora099 Date: Fri Nov 4 21:31:04 2022 +0530 fix: build commit 11f17a726f1fe389c60920a7be93eb9adbc44fa0 Author: danisharora099 Date: Fri Nov 4 21:18:43 2022 +0530 minor fixes commit d4741551a0946c1225aa8631deaa4fdb05e15a2c Author: danisharora099 Date: Fri Nov 4 20:58:42 2022 +0530 add: guide: waku-relay commit f67d3b26d65ec863ca330b17b447e084bf1b4db1 Author: danisharora099 Date: Fri Nov 4 20:08:33 2022 +0530 address comments commit 7eec7bcc72fb8f2949c4f76dcda63b04af6c450c Author: danisharora099 Date: Fri Nov 4 17:24:42 2022 +0530 add: content topic guide commit bc958ddb18bd35563e937ddd0650bdaf46e3494a Author: danisharora099 Date: Thu Nov 3 15:59:47 2022 +0530 address comments commit 0adcdceacae989cf384aaf50ba692d45faa3173a Author: danisharora099 Date: Thu Nov 3 12:42:49 2022 +0530 improve why waku commit cba05cc434e285da84d6ea1d3d110868919d3a01 Author: danisharora099 Date: Thu Nov 3 12:11:50 2022 +0530 rename concepts commit a403a2dc6b8bd303fd24ae746f538708f0f8f4eb Author: danisharora099 Date: Thu Nov 3 12:05:43 2022 +0530 update gitignore commit 57d7a79daf1995cce10a64c7d88009a2e6699b88 Author: danisharora099 Date: Thu Nov 3 12:05:01 2022 +0530 add cspell.json commit 05cbe6c9f51497dfcec2bca017caf7d83b30b5f8 Author: danisharora099 Date: Thu Nov 3 12:04:52 2022 +0530 address comments commit b9afeeed905d4919bbc07832f790f5a22c624929 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:34:41 2022 +0530 Update docs/Development Concepts/3.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 44043485708339982f6435ae52eee6f526421132 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:32:38 2022 +0530 Update docs/Development Concepts/2.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 9d152946c7ed0c2f0cefbeab6bfd19240d788546 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:32:28 2022 +0530 Update docs/Development Concepts/2.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit cb74f57e96451dc69f5ab06b5fbeda37ecc3e45c Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:32:15 2022 +0530 Update docs/Development Concepts/2.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit a8b7dcaf9f2502fc94bb6f1bbcce62881020a351 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:32:02 2022 +0530 Update docs/Development Concepts/2.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit ec6a8f2399eb43d99af40e64f5c76a678528337a Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:28:49 2022 +0530 Update docs/About/7.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit ed3f35959cf10ce372d84e5db7a241e1fa5e40e0 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:28:42 2022 +0530 Update docs/About/7.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 78ae346c05f266403b2ba0c9b320eb2fcb96fa74 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:28:35 2022 +0530 Update docs/About/6.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 2af69de57697c0f3addc323135d0e16e35894ddc Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Thu Nov 3 11:28:26 2022 +0530 Update docs/About/3.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 7b3e3519d2fa33627dfa2d19cab84c29639d90e8 Author: danisharora099 Date: Thu Nov 3 00:39:49 2022 +0530 iterate commit c37f84b91a7dbfa899c39f8357170ba94ed03324 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Wed Nov 2 15:30:56 2022 +0530 Update docs/Development Concepts/Protocols/2.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit b9b7c8f57eafbbc77b7f8e866eada71f3b147813 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Wed Nov 2 15:11:47 2022 +0530 Update docs/About/7.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit c0bf3a4778cfbc2bc821e96e54a370ddc9577ebc Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Wed Nov 2 15:11:07 2022 +0530 Update docs/About/6.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit a30737bd7cbfa4a4549caac0e256701aa16ca3d5 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Wed Nov 2 15:10:43 2022 +0530 Update docs/About/6.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 4a0851efebe332e767050688bcd7a231815aea3e Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Wed Nov 2 14:59:05 2022 +0530 Update docs/About/2.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 0ed49e6f2c143d1b13fe1d9b98ca777129edb657 Author: Danish Arora <35004822+danisharora099@users.noreply.github.com> Date: Wed Nov 2 14:58:56 2022 +0530 Update docs/About/1.md Co-authored-by: fryorcraken.eth <110212804+fryorcraken@users.noreply.github.com> commit 2793d8f8b7c29720c67ceffdf30a1ee5a6cdf4bd Author: danisharora099 Date: Tue Nov 1 19:51:24 2022 +0530 restructure & add new docs --- .cspell.json | 24 ++++++ .gitignore | 3 +- .vscode/settings.json | 3 + docs/About/1.md | 13 +++ docs/About/2.md | 28 +++++++ docs/About/3.md | 46 +++++++++++ docs/About/4.md | 32 ++++++++ docs/About/5.md | 15 ++++ docs/About/6.md | 21 +++++ docs/About/7.md | 16 ++++ docs/Concepts/1.md | 69 ++++++++++++++++ docs/Concepts/2.md | 11 +++ docs/Concepts/3.md | 46 +++++++++++ docs/Concepts/4.md | 60 ++++++++++++++ docs/Concepts/5.md | 19 +++++ docs/Concepts/6.md | 22 +++++ docs/Concepts/overview.png | Bin 0 -> 73394 bytes docs/choose-content-topic.md | 30 ------- docs/index.md | 29 ------- docs/protocols/index.md | 32 -------- docs/sign_messages_version_1.md | 98 ---------------------- docs/use cases/case-study-1.md | 3 - docs/use cases/case-study-2.md | 3 - docs/use cases/index.md | 3 - docusaurus.config.js | 139 ++++++++++++++++---------------- 25 files changed, 497 insertions(+), 268 deletions(-) create mode 100644 .cspell.json create mode 100644 .vscode/settings.json create mode 100644 docs/About/1.md create mode 100644 docs/About/2.md create mode 100644 docs/About/3.md create mode 100644 docs/About/4.md create mode 100644 docs/About/5.md create mode 100644 docs/About/6.md create mode 100644 docs/About/7.md create mode 100644 docs/Concepts/1.md create mode 100644 docs/Concepts/2.md create mode 100644 docs/Concepts/3.md create mode 100644 docs/Concepts/4.md create mode 100644 docs/Concepts/5.md create mode 100644 docs/Concepts/6.md create mode 100644 docs/Concepts/overview.png delete mode 100644 docs/choose-content-topic.md delete mode 100644 docs/index.md delete mode 100644 docs/protocols/index.md delete mode 100644 docs/sign_messages_version_1.md delete mode 100644 docs/use cases/case-study-1.md delete mode 100644 docs/use cases/case-study-2.md delete mode 100644 docs/use cases/index.md diff --git a/.cspell.json b/.cspell.json new file mode 100644 index 0000000..962242d --- /dev/null +++ b/.cspell.json @@ -0,0 +1,24 @@ +{ + "version": "0.2", + "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/master/cspell.schema.json", + "language": "en", + "words": ["waku"], + "flagWords": [], + "ignorePaths": [ + "package.json", + "package-lock.json", + "yarn.lock", + "tsconfig.json", + "node_modules/**" + ], + "patterns": [ + { "name": "multiaddr", "pattern": "/p2p.*/" }, + { "name": "dnsMultiaddr", "pattern": "//dns4.*/" }, + { "name": "wss", "pattern": "/wss:.*/" }, + { + "name": "youtube-link", + "pattern": "/< youtube.*/" + } + ], + "ignoreRegExpList": ["multiaddr", "dnsMultiaddr", "wss", "youtube-link"] +} diff --git a/.gitignore b/.gitignore index 3651560..bd5955b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Dependencies /node_modules + # Production /build @@ -15,8 +16,8 @@ .env.test.local .env.production.local + npm-debug.log* yarn-debug.log* yarn-error.log* -.idea \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5429fb5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["Waku"] +} diff --git a/docs/About/1.md b/docs/About/1.md new file mode 100644 index 0000000..59cb09c --- /dev/null +++ b/docs/About/1.md @@ -0,0 +1,13 @@ +--- +title: Introduction +--- + +Waku (v2) is family of modular peer-to-peer protocols for **secure communication**. The protocols are designed to be secure, privacy-preserving, censorship-resistant and able to run in resource restricted environments. + +It enables you to **add communication features** to your dApp in a **decentralized manner**, +ensuring to your users that they will not be censored or de-platformed. + +- **removes centralized third parties from messaging**: enabling private, secure, censorship-free communication with no single point of failure. +- provides **privacy-preserving capabilities**: sender anonymity, metadata protection and unlinkability to personally identifiable information. +- designed for **generalized messaging**: enables human-to-human, machine-to-machine or hybrid communication. +- **runs everywhere**: desktop, server, including resource-restricted devices, such as mobile devices and browsers. diff --git a/docs/About/2.md b/docs/About/2.md new file mode 100644 index 0000000..6fb09a1 --- /dev/null +++ b/docs/About/2.md @@ -0,0 +1,28 @@ +--- +title: History +--- + +Waku v1 was a fork of Whisper with some added tweaks for efficiency. +Waku v2 is a completely redesigned suite of protocols designed to address the goals set out [previously](./1). + +### 2013 + +Ethereum White Paper was introduced with the Holy Trinity, +consisting of Ethereum for consensus, Swarm for decentralized storage, and Whisper for p2p messaging. + +### 2015-2018 + +R&D of Whisper was slow to follow progress of the Ethereum EVM and Swarm without a dedicated team building out the protocol. + +### 2018 + +With little progress made on Whisper and significant scalability concerns growing, +Vac was formed to conduct R&D on more scalable p2p messaging. + +### 2020 + +Waku v1 was introduced as the messaging protocol in Status, replacing Whisper. + +### 2021 + +Waku v2 replaces Waku v1. diff --git a/docs/About/3.md b/docs/About/3.md new file mode 100644 index 0000000..fc0fea9 --- /dev/null +++ b/docs/About/3.md @@ -0,0 +1,46 @@ +--- +title: Motivation and goals +--- + +Waku as a family of protocols is designed to have a set of properties that are useful for many applications: + +1. **Generalized messaging.** + +Many applications require some form of messaging protocol to communicate between different subsystems or different nodes. +This messaging can be human-to-human or machine-to-machine or a mix. +Waku is designed to work for all these scenarios. + +2. **Peer-to-peer.** + +Applications sometimes have requirements that make them suitable for peer-to-peer solutions: + +- Censorship-resistant with no single point of failure +- Adaptive and scalable network +- Shared infrastructure/service network + +3. **Runs anywhere.** + +Applications often run in restricted environments, where resources or the environment is restricted in some fashion. +For example: + +- Limited bandwidth, CPU, memory, disk, battery, etc +- Not being publicly connectable +- Only being intermittently connected; mostly-offline + +4. **Privacy-preserving.** + +Applications often have a desire for some privacy guarantees, such as: + +- Pseudonymity and not being tied to any personally identifiable information (PII) +- Metadata protection in transit +- Various forms of unlinkability, etc + +5. **Modular design.** + +Waku nodes are [adaptive](https://rfc.vac.dev/spec/30/): you can turn several dials depending on your use case and environment. + +For example: + +- Low privacy/low resource usage vs high privacy/increased latency + bandwidth usage +- Providing resources to the network vs consuming resources +- Stronger guarantees for spam protection vs economic registration cost diff --git a/docs/About/4.md b/docs/About/4.md new file mode 100644 index 0000000..18bc224 --- /dev/null +++ b/docs/About/4.md @@ -0,0 +1,32 @@ +--- +title: Why Waku? +--- + +Communication today is rife with third party interference. +From censorship and deplatforming, to rent seeking intermediaries, to the misuse of data in the surveillance economy. + +Waku is designed to place control of communication back into the hands of the individual. + +It is the communication layer for Web3 -- **decentralized communication that scales**. + +- Waku fills the void left by Whisper. + +- We are building Waku as a public good for the Ethereum and multi-chain ecosystem. + +- It is not tied to a specific chain. + +- It is modular and adaptive, enabling various use cases. + +- It enables developers to decentralize communication in their dApps or move actions off-chain without compromising decentralization. + +- It aims to run anywhere, in the cloud and browser alike. + +Private. Secure. Runs anywhere. + +| | Whisper | Waku | +|----------------------------------------| ------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------: | +| **Scalability** | Whisper doesn't scale very well, specifically when it comes to bandwidth usage on mobile devices. | Uses gossipsub and content topics. | +| **Spam Resistance** | Proof of work requires too much battery and compute power making it a poor mechanism for heterogeneous nodes. | Uses innovative p2p economic spam protection mechanism RLN Relay | +| **No incentivized infrastructure** | There is no incentive to run a Whisper node | Research in progress to design incentivization for node operators. | +| **Formal Specification/Documentation** | Lack of formal and unambiguous specification | Open source specs & docs and available for anyone to read or improve. | +| **Portability** | Runs over devp2p which limits where Whisper can run and how | Waku is built using libp2p, making it easy to run Waku anywhere. | diff --git a/docs/About/5.md b/docs/About/5.md new file mode 100644 index 0000000..d909b11 --- /dev/null +++ b/docs/About/5.md @@ -0,0 +1,15 @@ +--- +title: Who is using Waku? +--- + +### Status + +[Status](https://status.im/) is a secure messaging app, crypto wallet, and Web3 browser built with state-of-the-art technology. + +### XMTP + +[XMTP](https://xmtp.org/) is using Waku v2 for their open protocol and network for secure web3 messaging. + +### RAILGUN + +[RAILGUN](https://railgun.org/) is a privacy system for Ethereum that shields your assets in your own smart contract wallet. RAILGUN uses Waku when offering the ETH gas payments to other users, privately signaling fees and offers for gas payment relayers to keep the privacy & anonymity of your stablecoin & token transactions. diff --git a/docs/About/6.md b/docs/About/6.md new file mode 100644 index 0000000..30411d6 --- /dev/null +++ b/docs/About/6.md @@ -0,0 +1,21 @@ +--- +title: Implementations +--- + +Waku has been implemented in multiple languages to cater to a variety of unique use-cases: + +#### [nwaku](https://github.com/status-im/nwaku) + +A nim implementation of the Waku v2 protocol. The reference implementation, recommended to deploy a node in the cloud or at home. + +#### [js-waku](https://github.com/waku-org/js-waku/) + +A JavaScript/TypeScript implementation for browser environments. + +#### [go-waku](https://github.com/status-im/go-waku) + +A Go implementation for native integration in go applications, C-Bindings are also available with C#, Swift and Kotlin examples. + +#### [@waku/react-native](https://github.com/waku-org/waku-react-native) + +Integrate Waku in your React Native app using go-waku for mobile. diff --git a/docs/About/7.md b/docs/About/7.md new file mode 100644 index 0000000..e0a4d1b --- /dev/null +++ b/docs/About/7.md @@ -0,0 +1,16 @@ +--- +title: How does it work? +--- + +The backbone of Waku Network is the Waku Relay protocol. +It is a pubsub protocol based on libp2p gossipsub. +Other Waku protocols have been defined to enable capabilities such as: + +1. retrieving **historical messages** for mostly-offline devices +2. key turn solution for **encrypted communication** (symmetric encryption, ECIES/asymmetric encryption, noise handshake). +3. preserving bandwidth usage for **resource-restricted devices** +4. Economic **spam protection** (rate limit) with privacy preserving capabilities +5. Mass deanonymization protection (research in progress) + + +If you want to learn how Waku works under the hoods, check out the [10/WAKU2](https://rfc.vac.dev/spec/10/) RFC. diff --git a/docs/Concepts/1.md b/docs/Concepts/1.md new file mode 100644 index 0000000..c4add40 --- /dev/null +++ b/docs/Concepts/1.md @@ -0,0 +1,69 @@ +--- +title: Protocols Explained +--- + +Currently the main protocols used for Waku are: + +### [Waku Relay](https://rfc.vac.dev/spec/11/) + +`WAKU2-RELAY` specifies a Publish/Subscribe approach to peer-to-peer messaging with a strong focus on privacy, censorship-resistance, security and scalability. +Its current implementation is a minor extension of the libp2p GossipSub protocol and prescribes gossip-based dissemination. + +An extension of this is `WAKU-RLN-RELAY`, a privacy-preserving economic spam protection mechanism. + +### [Waku Filter](https://rfc.vac.dev/spec/12/) + +`WAKU2-FILTER` is a protocol that enables subscribing to messages that a peer receives. +It enables a node to access the relay network without the connectivity and bandwidth requirements of relay nodes, but it comes with privacy drawbacks. +Light nodes subscribe to service nodes and only receive the messages they desire. + +This is used to make fetching of a subset of messages more bandwidth preserving. + +### [Waku Store](https://rfc.vac.dev/spec/13/) + +DApps running on a phone or in a browser are often offline: +The browser could be closed or mobile app in the background. + +[Waku Relay](https://rfc.vac.dev/spec/11/) is a gossip protocol. +As a user, it means that your peers forward you messages they just received. +If you cannot be reached by your peers, then messages are not relayed; +relay peers do **not** save messages for later. + +However, [Waku Store](https://rfc.vac.dev/spec/13/) peers do save messages they relay, +allowing you to retrieve them at a later time. +The Waku Store protocol is best-effort and does not guarantee data availability. +Waku Relay or Waku Filter should still be preferred when online; +Waku Store can be used after resuming connectivity: +For example, when the dApp starts. + +### [Waku Light Push](https://rfc.vac.dev/spec/19/) + +Waku Light Push enables a client to receive a confirmation when sending a message. + +The Waku Relay protocol sends messages to connected peers but does not provide any information on whether said peers have received messages. +This can be an issue when facing potential connectivity issues. +For example, when the connection drops easily, or it is connected to a small number of relay peers. + +Waku Light Push allows a client to get a response from a remote peer when sending a message. +Note this only guarantees that the remote peer has received the message, +it cannot guarantee propagation to the network. + +It also means weaker privacy properties as the remote peer knows the client is the originator of the message. +Whereas with Waku Relay, a remote peer would not know whether the client created or forwarded the message. + +You can find Waku Light Push's specifications on [Vac RFC](https://rfc.vac.dev/spec/19/). + +`WAKU2-LIGHTPUSH` is a request/response protocol for this. + +## Additional Protocols + +This is in addition to protocols that specify messages, payloads, and recommended usages. +For example: + +- [14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14) and [26/WAKU2-PAYLOAD](https://rfc.vac.dev/spec/26) for message payloads +- [23/WAKU2-TOPICS](https://rfc.vac.dev/spec/23) and [27/WAKU2-PEERS](https://rfc.vac.dev/spec/27) for recommendations around usage + +There are also more experimental libp2p protocols such as +[`WAKU-RLN-RELAY`](https://rfc.vac.dev/spec/17/) + +You can find more information on this [here](./6.md). diff --git a/docs/Concepts/2.md b/docs/Concepts/2.md new file mode 100644 index 0000000..27f0586 --- /dev/null +++ b/docs/Concepts/2.md @@ -0,0 +1,11 @@ +--- +title: Transports in Waku +--- + +Waku v2 is built in top of libp2p, and like libp2p it strives to be transport agnostic. We define a set of recommended transports in order to achieve a baseline of interoperability between clients. + +This section describes these recommended transports: + +- Waku nodes uses TCP to communicate by default. A service node should be using TCP to connect to other nodes and listen to +- In environments where TCP is not available, such as browser, secure websocket is used. service nodes are encouraged to setup a SSL certificate to enable incoming connections from browser and serve them. +- Other protocols such as [WebRTC](https://github.com/waku-org/js-waku/issues/20), [WebTransport](https://github.com/waku-org/js-waku/issues/697) and QUIC have been studied. diff --git a/docs/Concepts/3.md b/docs/Concepts/3.md new file mode 100644 index 0000000..4731ad0 --- /dev/null +++ b/docs/Concepts/3.md @@ -0,0 +1,46 @@ +--- +title: Content Topic and How to Choose One +--- + +A content topic is used for content based filtering and allows you to filter out the messages that your dApp processes, +both when receiving live messages (Relay or Filter) or retrieving historical messages (Store). + +The recommended format for content topics is as follows: + +`/{dapp-name}/{version}/{content-topic-name}/{encoding}` + +- `dapp-name`: The name of your dApp, it must be unique to avoid conflict with other dApps. +- `version`: We usually start at `1`, useful when introducing breaking changes in your messages. +- `content-topic-name`: The actual content topic name to use for filtering. + If your dApp uses Waku for several features, + you should use a content topic per feature. +- `encoding`: The encoding format of the message, [Protobuf](https://developers.google.com/protocol-buffers) is most often used: `proto`. + +For example: Your dApp's name is SuperCrypto, +it enables users to receive notifications and send private messages. +You may want to use the following content topics: + +- `/supercrypto/1/notification/proto` +- `/supercrypto/1/private-message/proto` + +## PubSub topic + +There is another type of a _topic_ in Waku: A pubsub topic is used for routing of messages between the relaying nodes in the Waku network. + +> This section talks more about how networking and relaying of messages is handled by the nodes in the network, +> and has little to do with the application layer of Waku. +> Feel free to skip ahead this section if you are not interested in the details of how Waku works. + +The format for a pubsub topic is as follows: +`/waku/2/{topic-name}/{encoding}` and the default pubsub topic is `/waku/2/default-waku/proto`. + +This indicates to: + +1. `waku`: Waku problem domain +2. `2`: Version is 2 +3. `default-waku`: Default topic for exchanging WakuMessages +4. `proto`: The data field in PubSub is serialized/encoded as Protobuf as determined by WakuMessage + +Unless there’s a good reason, the default PubSub topic is used for all protocols. However, in certain situations other topics may be used. + +Using a single PubSub topic ensures a connected network, as well some degree of metadata protection. See [Anonymity/Unlinkability](https://rfc.vac.dev/spec/10/#anonymity--unlinkability) for more details. diff --git a/docs/Concepts/4.md b/docs/Concepts/4.md new file mode 100644 index 0000000..1fb06b3 --- /dev/null +++ b/docs/Concepts/4.md @@ -0,0 +1,60 @@ +--- +title: Security Features +--- + +Each protocol layer of Waku v2 provides a distinct service and is associated with a separate set of security features and concerns. +Therefore, the overall security of Waku v2 depends on how the different layers are utilized. + +The security models are detailed in the RFC of the protocols. +That we strive to provide well documented and open source RFCs so that Waku users know what security guarantees are and aren't provided by each protocol. + +Some of the security features of Waku v2 are: + +### Pseudonymity + +Waku v2 by default guarantees pseudonymity for all of the protocol layers since parties do not have to disclose their true identity +and instead they utilize libp2p `PeerID` as their identifiers. +While pseudonymity is an appealing security feature, it does not guarantee full anonymity since the actions taken under the same pseudonym +i.e., `PeerID` can be linked together and potentially result in the re-identification of the true actor. + +### Anonymity / Unlinkability + +At a high level, anonymity is the inability of an adversary in linking an actor to its data/performed action (the actor and action are context-dependent). +To be precise about linkability, we use the term Personally Identifiable Information (PII) to refer to any piece of data that could potentially be used to uniquely identify a party. +For example, the signature verification key, and the hash of one's static IP address are unique for each user and hence count as PII. +Notice that users' actions can be traced through their PIIs (e.g., signatures) and hence result in their re-identification risk. +As such, we seek anonymity by avoiding linkability between actions and the actors / actors' PII. Concerning anonymity, Waku v2 provides the following features: + +**Publisher-Message Unlinkability**: +This feature signifies the unlinkability of a publisher to its published messages in the `WAKU-RELAY` protocol. + +**Subscriber-Topic Unlinkability**: +This feature stands for the unlinkability of the subscriber to its subscribed topics in the `WAKU-RELAY` protocol. +The [Subscriber-Topic Unlinkability](https://rfc.vac.dev/spec/11/#security-analysis) is achieved through the utilization of a single PubSub topic. +As such, subscribers are not re-identifiable from their subscribed topic IDs as the entire network is linked to the same topic ID. +This level of unlinkability / anonymity is known as [k-anonymity](https://www.privitar.com/blog/k-anonymity-an-introduction/) where k is proportional to the system size (number of subscribers). +Note that there is no hard limit on the number of the pubsub topics, however, the use of one topic is recommended for the sake of anonymity. + +### Spam protection + +This property indicates that no adversary can flood the system (i.e., publishing a large number of messages in a short amount of time), either accidentally or deliberately, with any kind of message i.e. even if the message content is valid or useful. +Spam protection is partly provided in `WAKU2-RELAY` through the [scoring mechanism](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#spam-protection-measures) provided for by GossipSub v1.1. +At a high level, peers utilize a scoring function to locally score the behavior of their connections and remove peers with a low score. + +There's also further research being done in this domain, including the designing of (RLN (Rate Limiting Nullifiers))[./7.md] + +### Data confidentiality, Integrity, and Authenticity + +Confidentiality can be addressed through data encryption whereas integrity and authenticity are achievable through digital signatures. +These features are provided for in [WAKU-MESSAGE (version 1)](https://rfc.vac.dev/spec/14#version-1) and [WAKU-NOISE](https://rfc.vac.dev/spec/35/) through payload encryption as well as encrypted signatures. + +> `WAKU-NOISE` enables secure channel negotiation over Waku. + +## Security Considerations + +**Lack of anonymity/unlinkability in the protocols involving direct connections including [`13/WAKU2-STORE`](https://rfc.vac.dev/spec/13/) and [`12/WAKU2-FILTER`](https://rfc.vac.dev/spec/12/) protocols**: +The anonymity/unlinkability is not guaranteed in the protocols like `13/WAKU2-STORE` and `12/WAKU2-FILTER` where peers need to have direct connections to benefit from the designated service. +This is because during the direct connections peers utilize `PeerID` to identify each other, +therefore the service obtained in the protocol is linkable to the beneficiary's `PeerID` (which counts as PII). +For `13/WAKU2-STORE`, the queried node would be able to link the querying node's `PeerID` to its queried topics. +Likewise, in the `12/WAKU2-FILTER`, a full node can link the light node's `PeerID`s to its content filter. diff --git a/docs/Concepts/5.md b/docs/Concepts/5.md new file mode 100644 index 0000000..5431749 --- /dev/null +++ b/docs/Concepts/5.md @@ -0,0 +1,19 @@ +--- +title: Research in Progress +--- + +The following features are currently experimental and under research and initial implementation: + +**Economic Spam resistance**: +We aim to enable an incentivized spam protection technique to enhance `WAKU-RELAY` by using rate limiting nullifiers. +More details on this can be found in [17/WAKU2-RLN-RELAY](https://rfc.vac.dev/spec/17). +In this advanced method, peers are limited to a certain rate of messaging per epoch and an immediate financial penalty is enforced for spammers who break this rate. + +**Prevention of Denial of Service (DoS) and Node Incentivization**: +Denial of service signifies the case where an adversarial node exhausts another node's service capacity (e.g., by making a large number of requests) and makes it unavailable to the rest of the system. +DoS attack is to be mitigated through the accounting model as described in [18/WAKU2-SWAP](https://rfc.vac.dev/spec/18). +In a nutshell, peers have to pay for the service they obtain from each other. +In addition to incentivizing the service provider, accounting also makes DoS attacks costly for malicious peers. +The accounting model can be used in `13/WAKU2-STORE` and `12/WAKU2-FILTER` to protect against DoS attacks. + +Additionally, this gives node operators who provide a useful service to the network an incentive to perform that service. diff --git a/docs/Concepts/6.md b/docs/Concepts/6.md new file mode 100644 index 0000000..3c4c92a --- /dev/null +++ b/docs/Concepts/6.md @@ -0,0 +1,22 @@ +--- +title: Waku vs libp2p - what's the difference? +--- + +Since Waku v2 is built on top of libp2p, they share a lot of concepts and terminologies between them. However, there are key differences between them that are worth noting. + +### Waku as a service network + +Waku offers incentivization mechanisms to run nodes, whereas libp2p does not. + +Additionally, a user or a developer does not have to deploy own infra as a prerequisite to use Waku, it is a service network. +However, it is encouraged to [run your own node](https://github.com/status-im/nwaku/tree/master/docs/operators) to support and decentralize the network. + +### Waku as a keyturn solution + +Waku includes a number of protocol covering the following domains like privacy preservation, censorship resistance, portability/runs anywhere. + +libp2p does not provide out of the box protocols to enable mostly offline/resource restricted devices, [WAKU-STORE](https://rfc.vac.dev/spec/13/)/[WAKU-LIGHTPUSH](https://rfc.vac.dev/spec/19/)/[WAKU-FILTER](https://rfc.vac.dev/spec/12/) caters to those use cases. + +### Economic spam protection + +libp2p does not have strong spam protection guarantees, [RLN (Rate Limit Nullifier)](https://rfc.vac.dev/spec/32/) is a protocol being developed by the Waku team towards this goal. diff --git a/docs/Concepts/overview.png b/docs/Concepts/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..bcf37474b96f4bbeb390aa89e8ceace2e1be701b GIT binary patch literal 73394 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

SnKMMh@!sX}C!yfTLyXU-6-P#6l}`NLBK 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 mU%Qmf`G5WJ)wmL?&Dfke-MA4^FDUpm>YZ_K$G - - -```shell -npm isntall js-waku -``` - - - - -```shell -yarn isntall js-waku -``` - - - - -```shell -pnpm isntall js-waku -``` - - - diff --git a/docs/sign_messages_version_1.md b/docs/sign_messages_version_1.md deleted file mode 100644 index ad88940..0000000 --- a/docs/sign_messages_version_1.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -summary: Demonstrate how to sign messages using Waku -authors: -- Fryorcraken -date: 2022-08-15 ---- - -# Sign Messages Using Waku Message Version 1 - -The Waku Message format provides an easy way to sign messages using elliptic curve cryptography. - -It also allows the sender to encrypt messages, -see [Encrypt Messages Using Waku Message Version 1](/) to learn how. - -You can find more details about Waku Message Payload Signature in [26/WAKU-PAYLOAD](https://rfc.vac.dev/spec/26/). - -See [Cryptographic Libraries](/) for more details on the cryptographic libraries used by js-waku. - -## Create new keypair - -Generate a new keypair to sign your messages: - -```ts -import { generatePrivateKey, getPublicKey } from "js-waku"; - -const privateKey = generatePrivateKey(); -const publicKey = getPublicKey(privateKey); -``` - -## Sign Waku Messages - -As per version 1's [specs](https://rfc.vac.dev/spec/26/), signatures are only included in encrypted messages. -In the case where your app does not need encryption then you could use symmetric encryption with a trivial key. - -You can learn more about encryption at [Encrypt Messages Using Waku Message Version 1](/). - -### Using symmetric encryption - -Given `symKey` the symmetric key used for encryption: - -```ts -import { WakuMessage } from "js-waku"; - -const message = await WakuMessage.fromBytes(payload, myAppContentTopic, { - encPublicKey: symKey, - sigPrivKey: privateKey, -}); -``` - -If encryption is not needed for your use case, -then you can create a symmetric key from the content topic: - -```ts -import { hexToBuf } from "js-waku/lib/utils"; -import { keccak256 } from "ethers/lib/utils"; - -const symKey = hexToBuf(keccak256(Buffer.from(myAppContentTopic, "utf-8"))); -``` - -`symKey` can then be used to encrypt and decrypt messages on `myAppContentTopic` content topic. -Read [How to Choose a Content Topic](/) to learn more about content topics. - -### Using asymmetric encryption - -Given `recipientPublicKey` the public key of the message's recipient: - -```ts -import { WakuMessage } from "js-waku"; - -const message = await WakuMessage.fromBytes(payload, myAppContentTopic, { - encPublicKey: recipientPublicKey, - sigPrivKey: privateKey, -}); -``` - -## Verify Waku Message signatures - -Two fields are available on signed `WakuMessage`s: - -- `signaturePublicKey`: Holds the public key of the signer, -- `signature`: Holds the actual signature. - -Thus, if you expect messages to be signed by Alice, -you can simply compare `WakuMessage.signaturePublicKey` with Alice's public key. -As comparing hex string can lead to issues (is the `0x` prefix present?), -simply use helper function `equalByteArrays`. - -```ts -import { equalByteArrays } from "js-waku/lib/utils"; - -const sigPubKey = wakuMessage.signaturePublicKey; - -const isSignedByAlice = sigPubKey && equalByteArrays(sigPubKey, alicePublicKey); - -if (!isSignedByAlice) { - // Message is not signed by Alice -} -``` diff --git a/docs/use cases/case-study-1.md b/docs/use cases/case-study-1.md deleted file mode 100644 index 8437fbf..0000000 --- a/docs/use cases/case-study-1.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Case study 1 ---- \ No newline at end of file diff --git a/docs/use cases/case-study-2.md b/docs/use cases/case-study-2.md deleted file mode 100644 index a59e53f..0000000 --- a/docs/use cases/case-study-2.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Case study 2 ---- \ No newline at end of file diff --git a/docs/use cases/index.md b/docs/use cases/index.md deleted file mode 100644 index 0d3d164..0000000 --- a/docs/use cases/index.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Use cases ---- \ No newline at end of file diff --git a/docusaurus.config.js b/docusaurus.config.js index 4bf4101..27f069b 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -1,105 +1,106 @@ // @ts-check // Note: type annotations allow type checking and IDEs autocompletion -const lightCodeTheme = require('prism-react-renderer/themes/github'); -const darkCodeTheme = require('prism-react-renderer/themes/dracula'); +const lightCodeTheme = require("prism-react-renderer/themes/github"); +const darkCodeTheme = require("prism-react-renderer/themes/dracula"); /** @type {import('@docusaurus/types').Config} */ const config = { title: "Waku guides", - tagline: 'Waku is the communication layer for Web3.', - url: 'https://waku.guides', - baseUrl: '/', - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', - favicon: 'img/favicon.ico', + tagline: "Waku is the communication layer for Web3.", + url: "https://waku.guides", + baseUrl: "/", + onBrokenLinks: "throw", + onBrokenMarkdownLinks: "warn", + favicon: "img/favicon.ico", // GitHub pages deployment config. // If you aren't using GitHub pages, you don't need these. - organizationName: 'waku-org', // Usually your GitHub org/user name. - projectName: 'waku.guide', // Usually your repo name. + organizationName: "waku-org", // Usually your GitHub org/user name. + projectName: "waku.guide", // Usually your repo name. // Even if you don't use internalization, you can use this field to set useful // metadata like html lang. For example, if your site is Chinese, you may want // to replace "en" with "zh-Hans". i18n: { - defaultLocale: 'en', - locales: ['en'], + defaultLocale: "en", + locales: ["en"], }, presets: [ [ - 'classic', + "classic", /** @type {import('@docusaurus/preset-classic').Options} */ ({ docs: { - sidebarPath: require.resolve('./sidebars.js'), + sidebarPath: require.resolve("./sidebars.js"), // Please change this to your repo. // Remove this to remove the "edit this page" links. editUrl: - 'https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/', + "https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/", }, theme: { - customCss: require.resolve('./src/css/custom.css'), + customCss: require.resolve("./src/css/custom.css"), }, }), ], ], - themeConfig: - ({ - colorMode: { - defaultMode: 'dark', - disableSwitch: false, - respectPrefersColorScheme: true + themeConfig: { + colorMode: { + defaultMode: "dark", + disableSwitch: false, + respectPrefersColorScheme: true, + }, + navbar: { + title: "Waku", + logo: { + alt: "Waku Logo", + src: "img/logo.svg", }, - navbar: { - title: 'Waku', - logo: { - alt: 'My Site Logo', - src: 'img/logo.svg', + + items: [ + { + type: "doc", + docId: "About/1", + position: "left", + label: "About", }, - items: [ - { - type: 'doc', - docId: 'index', - position: 'left', - label: 'Guides', - }, - { - href: 'https://github.com/facebook/docusaurus', - label: 'GitHub', - position: 'right', - }, - ], - }, - footer: { - style: 'dark', - links: [ - { - title: 'Community', - items: [ - { - label: 'Stack Overflow', - href: 'https://stackoverflow.com/questions/tagged/docusaurus', - }, - { - label: 'Discord', - href: 'https://discordapp.com/invite/docusaurus', - }, - { - label: 'Twitter', - href: 'https://twitter.com/docusaurus', - }, - ], - } - ], - copyright: `Copyright © ${new Date().getFullYear()} My Project, Inc. Built with Docusaurus.`, - }, - prism: { - theme: lightCodeTheme, - darkTheme: darkCodeTheme, - }, - }), + { + type: "doc", + docId: "Concepts/1", + position: "left", + label: "Concepts", + }, + ], + }, + footer: { + style: "dark", + links: [ + { + title: "Community", + items: [ + { + label: "Stack Overflow", + href: "https://stackoverflow.com/questions/tagged/docusaurus", + }, + { + label: "Discord", + href: "https://discordapp.com/invite/docusaurus", + }, + { + label: "Twitter", + href: "https://twitter.com/docusaurus", + }, + ], + }, + ], + copyright: `Copyright © ${new Date().getFullYear()} Status Gmbh. Built with Docusaurus.`, + }, + prism: { + theme: lightCodeTheme, + darkTheme: darkCodeTheme, + }, + }, }; module.exports = config;