Compare commits

..

21 Commits

Author SHA1 Message Date
Jimmy Debe
a101e02f82 Update validator.md 2024-08-06 23:51:01 -04:00
Jimmy Debe
2d62ad438a Update validator.md 2024-07-19 07:52:28 -04:00
Jimmy Debe
1e8641d965 Create validator.md 2024-07-17 10:33:12 -04:00
Jimmy Debe
89cac77ae4 feat(60/STATUS-URL-SCHEME): initial draft (#14)
Moved from https://github.com/status-im/specs/pull/159

Reference pull request: https://github.com/vacp2p/rfc/pull/602
2024-06-21 08:35:42 -04:00
Jimmy Debe
a189a72146 fix: messageHash in 57 (#22) 2024-06-14 16:51:31 +02:00
Jimmy Debe
cbefa483fc 32/RLN-V1: Move to Draft (#40)
Update 32/RLN-V1 to move to draft.

---------

Co-authored-by: Aaryamann Challani <43716372+rymnc@users.noreply.github.com>
2024-06-06 09:39:56 -04:00
Jimmy Debe
5064ded998 Update 17/WAKU2-RLN-RELAY: Proof Size (#44)
Update proof size description based on discussion
[here](https://github.com/waku-org/nwaku/issues/2757).
2024-06-06 09:39:32 -04:00
Jimmy Debe
7b443c1aab 17/WAKU2-RLN-RELAY: Update (#32)
Move 17/WAKU2-RLN-RELAY to stable open discussion. 
Implementation :
- [ nim ](https://github.com/waku-org/nwaku)
- [ go ](https://github.com/waku-org/go-waku)
2024-05-28 22:27:45 -04:00
Jimmy Debe
99be3b9745 Move Raw Specs (#37)
Move Vac raw specs into raw subdirectory.
2024-05-27 07:57:18 -04:00
ramsesfv
7e3a625812 ETH-SECPM-DEC (#28)
Co-authored-by: Jimmy Debe <91767824+jimstir@users.noreply.github.com>
Co-authored-by: Ekaterina Broslavskaya <seemenkina@gmail.com>
Co-authored-by: seugu <99656002+seugu@users.noreply.github.com>
2024-05-27 12:15:46 +02:00
ramsesfv
e234e9d5a3 Update eth-secpm.md (#35)
Added flow diagrams

---------

Co-authored-by: Jimmy Debe <91767824+jimstir@users.noreply.github.com>
2024-05-21 11:21:34 +02:00
Jimmy Debe
e5b859abfb Update WAKU2-NETWORK: Move to draft (#5) 2024-05-10 16:41:48 +02:00
Filip Pajic
69f2853407 fix: Syntax fix for index documents inside Waku foldersFix syntax (#34)
# What does this PR resolve? 🚀
- Changes title inside Waku/README.md from h2 to h1
- Changes title inside Waku/Deprecated/README.md from h2 to h1

# Details 📝
The syntax for the title of the markdown seems to not be proper one
comparing to other README documents.
It's important to define titles with h1(#) to be able to parse it
properly later on by the website
2024-04-23 14:17:17 -04:00
Hanno Cornelius
8f94e97cf2 docs: deprecate swap protocol (#31)
Deprecates swap protocol.
2024-04-18 13:38:26 -04:00
Jimmy Debe
d82eaccdc0 Update WAKU2-METADATA: Move to draft (#6)
Move 66/WAKU2-METADATA to draft.
2024-04-17 15:24:44 -04:00
LordGhostX
8b552ba2e0 chore: mark 16/WAKU2-RPC as deprecated (#30) 2024-04-16 15:43:27 +02:00
Jimmy Debe
0b0e00f510 feat(rln-stealth-commitments): add initial tech writeup (#23)
By: rymnc
Reference pull request: https://github.com/vacp2p/rfc/pull/658

Initial writeup on viability of stealth commitments for status
communities

---------

Co-authored-by: fryorcraken <110212804+fryorcraken@users.noreply.github.com>
2024-04-15 17:34:56 +05:30
Jimmy Debe
43f4989bb1 Fix Markdown Lint (#25)
The linter was not checking any files.
2024-03-26 17:42:18 +01:00
Jimmy Debe
7698e60d58 RFC Website Workflow Sync (#27)
A workflow to sync this repository with the rfc website.
2024-03-26 17:41:58 +01:00
Jimmy Debe
2eaa7949c4 Broken Links + Change Editors (#26)
Fix to broken links, changed links, and added new editors to spec, 10,
12, 14, 17, 19.
2024-03-21 10:08:40 -04:00
Jimmy Debe
92d8cf339b Add Markdown Linting (#24) 2024-03-08 16:41:51 +01:00
46 changed files with 2039 additions and 496 deletions

32
.github/workflows/markdown-lint.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: markdown-linting
on:
push:
branches:
- '**'
pull_request:
branches:
- '**'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get changed files
continue-on-error: true
run: |
echo "CHANGED_FILES<<EOF" >> $GITHUB_ENV
gh pr diff ${{ github.event.number }} --name-only | sed -e 's|$|,|' | xargs -i echo "{}" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Markdown Linter
uses: DavidAnson/markdownlint-cli2-action@v15
with:
globs: ${{ env.CHANGED_FILES }}

41
.github/workflows/website-sync.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Website Sync
on:
pull_request:
types: [closed]
branches:
- main
jobs:
sync:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Clone Website Repo
run: |
git clone git@github.com:vacp2p/rfc-website.git
cd rfc-website
git config --local user.email "actions@github.com"
git config --local user.name "GitHub Actions"
- name: List of changed files
id: changed_files
run: |
echo "::set-output name=files::$(git diff --name-only ${{ github.event.before }} ${{ github.sha }})"
- name: Copy changed files to Website Repo
run: |
for file in ${{ steps.changed_files.outputs.files }}; do
cp --parents "$file" rfc-website/
done
- name: Push changes to Website Repo
run: |
cd rfc-website
git add .
git commit -m "Sync website"
git push origin main

73
codex/raw/validator.md Normal file
View File

@@ -0,0 +1,73 @@
---
title: CODEX-VALIDATOR
name: Codex Validator
status: raw
editor:
contributors:
---
## Abstract
This specification describes the Codex validation process for a Codex marketplace storage request.
The process is a remote auditing scheme to check that a piece of data is being stored on a storage node
## Background
Codex network has a few node roles that user can decide to run.
The validator role allows user to have some guarantee that there data is retrievable.
Codex storage contracts are create when a storage request is made by a user.
The node roles that participant in the storage contract will be the Codex client node and the Codex storage provider,
see [other rfc for more info](#).
Once an agreement is created between both node roles,
the client node will be aware that there data is being persisted and
storage nodes are aware that they are receiving periodic rewards from the new contract.
A storage provider may be an malicious actor by joining a contract in the beginning,
then stop storing the data shortly after for any malicious reason.
To avoid such a scenario, the Codex Marketplace allows for validator nodes to check data being stored.
Once a contract is opened,
storage nodes need to prove that they are still storing the data in the request.
This will give storage requesters assurances that the data is being persisted throughout the lifecycle of the storage contract. need to give assurances to requesters.
Malicious storage providers also need an disincentive to not store data and break the storage contract.
## Wire Format
Validator nodes choose
Before a validator node can validate a proof of storage,
a storage request MUST be active, and
each slot state MUST be `filled`.
While a slot is in `filled` state,
a validator has the ability to change the state to `empty`.
Slot state are SHOULD be stored on a EVM compatiable blockchain.
Validators MUST manually update state through the Codex Marketplace smart contract.
The following must be fulfilled before a state can be updated to `empty`.
### Flow
- Validators choose a random slot to download from a storage provider
- If the validator must create a proof of the data to match the proof already in the slot
- If the proof does not match, the slot is empty and validator marks it as `proofMissing`
- If the data cannot be downloaded,
the storage provider may be disconnected, the validator MAY mark slot as `proofMissing`
- If the data downloaded matchs the proof, the validator MAY makr slot as `correctProof`
The validator must make a blockchain transaction to state the current status of a slot.
- When a slot is missing and the validator marks it as `proofMissing`,
the slot MUST enter into repair, see [slot repair](CODEX-MARKETPLACE).
- The validator will recieve a reward for marking a `proofMissing`
A validator can continue this process for any duration.
### Validator Verifing Proofs
Each slot SHOULD contain the following:
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
1. [CODEX-MARKETPLACE](#)

View File

@@ -40,7 +40,7 @@ This document describes how 2 peers communicate with each other to send messages
This protocol MAY use any key-exchange mechanism previously discussed -
1. [53/WAKU2-X3DH](../../waku/standards/application/53/x3dh.md)
2. [WAKU2-NOISE](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise.md)
2. [WAKU2-NOISE](https://github.com/waku-org/specs/blob/master/standards/application/noise.md)
This protocol can provide end-to-end encryption to give peers 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.
@@ -67,7 +67,7 @@ It is handled by the key-exchange protocol used. For example,
1. [53/WAKU2-X3DH](../../waku/standards/application/53/x3dh.md), the session management is described in [54/WAKU2-X3DH-SESSIONS](../../waku/standards/application/54/x3dh-sessions.md)
2. [WAKU2-NOISE](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise.md), the session management is described in [WAKU2-NOISE-SESSIONS](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise-sessions/noise-sessions.md)
2. [WAKU2-NOISE](https://github.com/waku-org/specs/blob/master/standards/application/noise.md), the session management is described in [WAKU2-NOISE-SESSIONS](https://github.com/waku-org/specs/blob/master/standards/application/noise-sessions.md)
## Negotiation of a 1:1 chat amongst multiple participants (group chat)
@@ -203,7 +203,7 @@ To change the display image of the group chat, group admins MUST use an `IMAGE_C
## Security Considerations
1. Inherits the security considerations of the key-exchange mechanism used, e.g., [53/WAKU2-X3DH](../../waku/standards/application/53/x3dh.md) or [WAKU2-NOISE](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise.md)
1. Inherits the security considerations of the key-exchange mechanism used, e.g., [53/WAKU2-X3DH](../../waku/standards/application/53/x3dh.md) or [WAKU2-NOISE](https://github.com/waku-org/specs/blob/master/standards/application/noise.md)
## Copyright
@@ -212,10 +212,10 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
## References
1. [53/WAKU2-X3DH](../../waku/standards/application/53/x3dh.md)
2. [35/WAKU2-NOISE](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise.md)
2. [WAKU2-NOISE](https://github.com/waku-org/specs/blob/master/standards/application/noise.md)
3. [65/STATUS-ACCOUNT](../65/account-address.md)
4. [54/WAKU2-X3DH-SESSIONS](../../waku/standards/application/54/x3dh-sessions.md)
5. [37/WAKU2-NOISE-SESSIONS](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise-sessions/noise-sessions.md)
5. [WAKU2-NOISE-SESSIONS](https://github.com/waku-org/specs/blob/master/standards/application/noise-sessions.md)
6. [56/STATUS-COMMUNITIES](../56/communities.md)
7. [chat_message.proto](https://github.com/status-im/status-go/blob/5fd9e93e9c298ed087e6716d857a3951dbfb3c1e/protocol/protobuf/chat_message.proto#L1)
8. [emoji_reaction.proto](https://github.com/status-im/status-go/blob/5fd9e93e9c298ed087e6716d857a3951dbfb3c1e/protocol/protobuf/emoji_reaction.proto)

View File

@@ -321,7 +321,7 @@ There are two scenarios in which member nodes can receive such a magnet link mes
2. The member node requests messages for a time range of up to 30 days from store nodes (this is the case when a new community member joins a community)
### Downloading message archives
When member nodes receive a message with a `CommunityMessageHistoryArchive` ([62/STATUS-PAYLOAD](../62/payload.md)) from the aforementioned channnel, they MUST extract the `magnet_uri` and pass it to their underlying BitTorrent client so they can fetch the latest message history archive index, which is the `index` file of the torrent (see [Creating message archive torrents](#creating-message-archive-torrents)).
When member nodes receive a message with a `CommunityMessageHistoryArchive` ([62/STATUS-PAYLOADS](../62/payloads.md)) from the aforementioned channnel, they MUST extract the `magnet_uri` and pass it to their underlying BitTorrent client so they can fetch the latest message history archive index, which is the `index` file of the torrent (see [Creating message archive torrents](#creating-message-archive-torrents)).
Due to the nature of distributed systems, there's no guarantee that a received message is the "last" message. This is especially true when member nodes request historical messages from store nodes.
@@ -389,4 +389,4 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
* [Extensions for Peers to Send Metadata Files](https://www.bittorrent.org/beps/bep_0009.html)
* [org channels spec](../56/communities.md)
* [14/WAKU2-MESSAGE](../../waku/standards/core/14/message.md)
* [62/STATUS-PAYLOAD](../62/payload.md)
* [62/STATUS-PAYLOADS](../62/payloads.md)

View File

@@ -367,7 +367,7 @@ Operators can freely choose how they want to generate, and distribute the public
The following concepts are introduced:
* `private-key-topic`: A private key of 32 bytes, that allows the holder to sign messages and it's mapped to a `protected-pubsub-topic`.
* `app-message-hash`: Application `WakuMessage` hash, calculated as `sha256(concat(pubsubTopic, payload, contentTopic))` with all elements in bytes.
* `app-message-hash`: Application `WakuMessage` hash, calculated as `sha256(concat(pubsubTopic, payload, contentTopic, timestamp, ephemeral))` with all elements in bytes.
* `message-signature`: ECDSA signature of `application-message-hash` using a given `private-key-topic`, 64 bytes.
* `public-key-topic`: The equivalent public key of `private-key-topic`.
* `protected-pubsub-topic`: Pubsub topic that only accepts messages that were signed with `private-key-topic`, where `verify(message-signature, app-message-hash, public-key-topic)` is only correct if the `message-signature` was produced by `private-key-topic`. See ECDSA signature verification algorithm.

View File

@@ -9,7 +9,7 @@ contributors:
`25/LIBP2P-DNS-DISCOVERY` specifies a scheme to implement [`libp2p`](https://libp2p.io/) peer discovery via DNS for Waku v2.
The generalised purpose is to retrieve an arbitrarily long, authenticated, updateable list of [`libp2p` peers](https://docs.libp2p.io/concepts/peer-id/) to bootstrap connection to a `libp2p` network.
Since [`10/WAKU2`](https://rfc.vac.dev/spec/10/) currently specifies use of [`libp2p` peer identities](https://docs.libp2p.io/concepts/peer-id/),
Since [`10/WAKU2`](../../waku/standards/core/10/waku2.md) currently specifies use of [`libp2p` peer identities](https://docs.libp2p.io/concepts/peer-id/),
this method is suitable for a new Waku v2 node to discover other Waku v2 nodes to connect to.
This specification is largely based on [EIP-1459](https://eips.ethereum.org/EIPS/eip-1459),
@@ -126,7 +126,7 @@ Copyright and related rights waived via
# References
1. [`10/WAKU2`](https://rfc.vac.dev/spec/10/)
1. [`10/WAKU2`](../../waku/standards/core/10/waku2.md)
1. [EIP-1459: Client Protocol](https://eips.ethereum.org/EIPS/eip-1459#client-protocol)
1. [EIP-1459: Node Discovery via DNS ](https://eips.ethereum.org/EIPS/eip-1459)
1. [`libp2p`](https://libp2p.io/)

View File

@@ -2,14 +2,15 @@
slug: 32
title: 32/RLN-V1
name: Rate Limit Nullifier
status: raw
editor: Rasul Ibragimov <curryrasul@gmail.com>
status: draft
editor: Aaryamann Challani <aaryamann@status.im>
contributors:
- Barry Whitehat <barrywhitehat@protonmail.com>
- Sanaz Taheri <sanaz@status.im>
- Oskar Thorén <oskarth@titanproxy.com>
- Onur Kilic <onurkilic1004@gmail.com>
- Blagoj Dimovski <blagoj.dimovski@yandex.com>
- Rasul Ibragimov <curryrasul@gmail.com>
---
## Abstract
@@ -22,19 +23,25 @@ Anonymity refers to the unlinkability of messages to their owner.
RLN guarantees a messaging rate is enforced cryptographically while preserving the anonymity of the message owners.
A wide range of applications can benefit from RLN and provide desirable security features.
For example, an e-voting system can integrate RLN to contain the voting rate while protecting the voters-vote unlinkability.
Another use case is to protect an anonymous messaging system against DDoS and spam attacks by containing messaging rate of users.
For example,
an e-voting system can integrate RLN to contain the voting rate while protecting the voters-vote unlinkability.
Another use case is to protect an anonymous messaging system against DDoS and
spam attacks by constraining messaging rate of users.
This latter use case is explained in [17/WAKU2-RLN-RELAY RFC](../../waku/standards/core/17/rln-relay.md).
## Wire Format Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [2119](https://www.ietf.org/rfc/rfc2119.txt).
## Flow
### Flow
The users participate in the protocol by first registering to an application-defined group referred by the _membership group_.
Registration to the group is mandatory for signaling in the application.
After registration, group members can generate Zero-knowledge Proof of membership for their signals and can participate in the application.
Usually, the membership requires a financial or social stake which
is beneficial for the prevention of Sybil attacks and double-signaling.
Group members are allowed to send one signal per external nullifier (an identifier that groups signals and can be thought of as a voting booth).
After registration, group members can generate a zero-knowledge proof of membership for their signals and
can participate in the application.
Usually, the membership requires a financial or
social stake which is beneficial for the prevention of inclusion of Sybils within the _membership group_.
Group members are allowed to send one signal per external nullifier
(an identifier that groups signals and can be thought of as a voting booth).
If a user generates more signals than allowed,
the user risks being slashed - by revealing his membership secret credentials.
If the financial stake is put in place, the user also risks his stake being taken.
@@ -45,95 +52,108 @@ Generally the flow can be described by the following steps:
2. Signaling
3. Verification and slashing
## Registration
### Registration
Depending on the application requirements, the registration can be implemented in different ways, for example:
- centralized registrations, by using a central server
- decentralized registrations, by using a smart contract
What is important is that the users' identity commitments (explained in section [User Indetity](#user-identity)) are stored in a Merkle tree,
The users' identity commitments
(explained in section [User Identity](#user-identity)) are stored in a Merkle tree,
and the users can obtain a Merkle proof proving that they are part of the group.
Also depending on the application requirements,
usually a financial or social stake is introduced.
An example for financial stake is:
An example for financial stake is: For each registration a certain amount of ETH is required.
An example for social stake is using InterRep as a registry -
For each registration a certain amount of ETH is required.
An example for social stake is using [Interep](https://interep.link/) as a registry -
users need to prove that they have a highly reputable social media account.
### Implementation notes
#### Implementation notes
#### User identity
##### User identity
The user's identity is composed of:
```
```js
{
identity_secret: [identity_nullifier, identity_trapdoor],
identity_secret_hash: poseidonHash(identity_secret),
identity_commitment: poseidonHash([identity_secret_hash])
}
```
For registration, the user needs to submit their `identity_commitment` (along with any additional registration requirements) to the registry.
Upon registration, they should receive `leaf_index` value which represents their position in the Merkle tree.
For registration, the user MUST submit their `identity_commitment`
(along with any additional registration requirements) to the registry.
Upon registration, they SHOULD receive `leaf_index` value which represents their position in the Merkle tree.
Receiving a `leaf_index` is not a hard requirement and is application specific.
The other way around is the users calculating the `leaf_index` themselves upon successful registration.
## Signaling
### Signaling
After registration,
the users can participate in the application by sending signals to the other participants in a decentralised manner or to a centralised server.
the users can participate in the application by sending signals to the other participants in a decentralised manner or
to a centralised server.
Along with their signal,
they need to generate a ZK-Proof by using the circuit with the specification described above.
they MUST generate a zero-knowledge proof by using the circuit with the specification described above.
For generating a proof,
the users need to obtain the required parameters or compute them themselves,
depending on the application implementation and client libraries supported by the application.
For example the users can store the membership Merkle tree on their end and
For example,
the users MAY store the membership Merkle tree on their end and
generate a Merkle proof whenever they want to generate a signal.
### Implementation notes
#### Implementation notes
#### Signal hash
##### Signal hash
The signal hash can be generated by hashing the raw signal (or content) using the `keccak256` hash function.
#### External nullifier
##### External nullifier
The external nullifier MUST be computed as the Poseidon hash of the current epoch (e.g. a value equal to or derived from the current UNIX timestamp divided by the epoch length) and the RLN identifier.
The external nullifier MUST be computed as the Poseidon hash of the current epoch
(e.g. a value equal to or derived from the current UNIX timestamp divided by the epoch length) and
the RLN identifier.
```js
external_nullifier = poseidonHash([epoch, rln_identifier]);
```
external_nullifier = poseidonHash([epoch, rln_identifier])
```
#### Obtaining Merkle proof
##### Obtaining Merkle proof
The Merkle proof should be obtained locally or from a trusted third party.
The Merkle proof SHOULD be obtained locally or from a trusted third party.
By using the [incremental Merkle tree algorithm](https://github.com/appliedzkp/incrementalquintree/blob/master/ts/IncrementalQuinTree.ts),
the Merkle can be obtained by providing the `leaf_index` of the `identity_commitment`.
The proof (`Merkle_proof`) is composed of the following fields:
```
```js
{
root: bigint
indices: number[]
root: bigint,
indices: number[],
path_elements: bigint[][]
}
```
1. **root** - The root of membership group Merkle tree at the time of publishing the message
2. **indices** - The index fields of the leafs in the Merkle tree - used by the Merkle tree algorithm for verification
3. **path_elements** - Auxiliary data structure used for storing the path to the leaf - used by the Merkle proof algorithm for verificaton
3. **path_elements** - Auxiliary data structure used for storing the path to the leaf -
used by the Merkle proof algorithm for verificaton
#### Generating proof
##### Generating proof
For proof generation,
the user need to submit the following fields to the circuit:
the user MUST submit the following fields to the circuit:
```js
```
{
identity_secret: identity_secret_hash,
path_elements: Merkle_proof.path_elements,
@@ -141,10 +161,10 @@ the user need to submit the following fields to the circuit:
x: signal_hash,
external_nullifier: external_nullifier
}
```
#### Calculating output
##### Calculating output
The proof output is calculated locally,
in order for the required fields for proof verification to be sent along with the proof.
@@ -152,55 +172,61 @@ The proof output is composed of the `y` share of the secret equation and the `in
The `internal_nullifier` represents a unique fingerprint of a user for a given `epoch` and app.
The following fields are needed for proof output calculation:
```
```js
{
identity_secret_hash: bigint,
external_nullifier: bigint,
x: bigint,
x: bigint
}
```
The output `[y, internal_nullifier]` is calculated in the following way:
```
a_0 = identity_secret_hash
a_1 = poseidonHash([a0, external_nullifier])
```js
y = a_0 + x * a_1
a_0 = identity_secret_hash;
a_1 = poseidonHash([a0, external_nullifier]);
y = a_0 + x * a_1;
internal_nullifier = poseidonHash([a_1]);
internal_nullifier = poseidonHash([a_1])
```
It relies on the properties of the [Shamir's Secret sharing scheme](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing).
#### Sending the output message
##### Sending the output message
The user's output message (`output_message`),
containing the signal should contain the following fields at minimum:
containing the signal SHOULD contain the following fields at minimum:
```js
```
{
signal: signal, # non-hashed signal
signal: signal, # non-hashed signal,
proof: zk_proof,
internal_nullifier: internal_nullifier,
x: x, # signal_hash
x: x, # signal_hash,
y: y,
rln_identifier: rln_identifier
}
```
Additionally depending on the application,
the following fields might be required:
the following fields MAY be required:
```js
```
{
root: Merkle_proof.root,
epoch: epoch
}
```
## Verification and slashing
### Verification and slashing
The slashing implementation is dependent on the type of application.
If the application is implemented in a centralised manner,
@@ -209,19 +235,22 @@ the slashing will be implemented only on the server.
Otherwise if the application is distributed,
the slashing will be implemented on each user's client.
### Implementation notes
#### Implementation notes
Each user of the protocol (server or otherwise) will need to store metadata for each message received by each user,
Each user of the protocol
(server or otherwise) MUST store metadata for each message received by each user,
for the given `epoch`.
The data can be deleted when the `epoch` passes.
Storing metadata is required, so that if a user sends more than one unique signal per `epoch`,
Storing metadata is REQUIRED, so that if a user sends more than one unique signal per `epoch`,
they can be slashed and removed from the protocol.
The metadata stored contains the `x`, `y` shares and the `internal_nullifier` for the user for each message.
The metadata stored contains the `x`, `y` shares and
the `internal_nullifier` for the user for each message.
If enough such shares are present, the user's secret can be retreived.
One way of storing received metadata (`messaging_metadata`) is the following format:
```
```js
{
[external_nullifier]: {
[internal_nullifier]: {
@@ -230,14 +259,15 @@ One way of storing received metadata (`messaging_metadata`) is the following for
}
}
}
```
#### Verification
##### Verification
The output message verification consists of the following steps:
- `external_nullifier` correctness
- non-duplicate message check
- `zk_proof` verification
- `zk_proof` zero-knowledge proof verification
- spam verification
**1. `external_nullifier` correctness**
@@ -247,16 +277,18 @@ If the `external_nullifier` is correct the verification continues, otherwise, th
**2. non-duplicate message check**
The received message is checked to ensure it is not duplicate.
The duplicate message check is performed by verifying that the `x` and `y` fields do not exist in the `messaging_metadata` object.
The duplicate message check is performed by verifying that the `x` and `y`
fields do not exist in the `messaging_metadata` object.
If the `x` and `y` fields exist in the `x_shares` and `y_shares` array for the `external_nullifier` and
the `internal_nullifier` the message can be considered as a duplicate.
Duplicate messages are discarded.
**3. `zk_proof` verification**
The `zk_proof` should be verified by providing the `zk_proof` field to the circuit verifier along with the `public_signal`:
The `zk_proof` SHOULD be verified by providing the `zk_proof` field to the circuit verifier along with the `public_signal`:
```js
```
[
y,
Merkle_proof.root,
@@ -264,6 +296,7 @@ The `zk_proof` should be verified by providing the `zk_proof` field to the circu
x, # signal_hash
external_nullifier
]
```
If the proof verification is correct,
@@ -271,28 +304,30 @@ the verification continues, otherwise the message is discarded.
**4. Double signaling verification**
After the proof is verified the `x`, and `y` fields are added to the `x_shares` and `y_shares` arrays of the `messaging_metadata` `external_nullifier` and `internal_nullifier` object.
After the proof is verified the `x`, and `y` fields are added to the `x_shares` and `y_shares`
arrays of the `messaging_metadata` `external_nullifier` and `internal_nullifier` object.
If the length of the arrays is equal to the signaling threshold (`limit`), the user can be slashed.
#### Slashing
##### Slashing
After the verification, the user can be slashed if two different shares are present to reconstruct their `identity_secret_hash` from `x_shares` and `y_shares` fields,
for their `internal_nullifier`.
After the verification,
the user SHOULD be slashed if two different shares are present to reconstruct their `identity_secret_hash` from `x_shares` and `y_shares` fields, for their `internal_nullifier`.
The secret can be retreived by the properties of the Shamir's secret sharing scheme.
In particular the secret (`a_0`) can be retrieved by computing [Lagrange polynomials](https://en.wikipedia.org/wiki/Lagrange_polynomial).
After the secret is retreived,
the user's `identity_commitment` can be generated from the secret and it can be used for removing the user from the membership Merkle tree (zeroing out the leaf that contains the user's `identity_commitment`).
Additionally, depending on the application the `identity_secret_hash` can be used for taking the user's provided stake.
the user's `identity_commitment` SHOULD be generated from the secret and
it can be used for removing the user from the membership Merkle tree
(zeroing out the leaf that contains the user's `identity_commitment`).
Additionally, depending on the application the `identity_secret_hash` MAY be used for taking the user's provided stake.
## Technical overview
### Technical overview
The main RLN construct is implemented using a [ZK-SNARK](https://z.cash/technology/zksnarks/) circuit.
However, it is helpful to describe the other necessary outside components for interaction with the circuit,
which together with the ZK-SNARK circuit enable the above mentioned features.
### Terminology
#### Terminology
| Term | Description |
|---------------------------|-------------------------------------------------------------------------------------|
@@ -301,7 +336,7 @@ which together with the ZK-SNARK circuit enable the above mentioned features.
| **Identity secret** | An array of two unique random components (identity nullifier and identity trapdoor), which must be kept private by the user. Secret hash and identity commitment are derived from this array. |
| **Identity nullifier** | Random 32 byte value used as component for identity secret generation. |
| **Identity trapdoor** | Random 32 byte value used as component for identity secret generation. |
| **Identity secret hash** | The hash of the identity secret, obtained using the Poseidon hash function. It is used for deriving the identity commitment of the user, and as a private input for zk proof generation. The secret hash should be kept private by the user. |
| **Identity secret hash** | The hash of the identity secret, obtained using the Poseidon hash function. It is used for deriving the identity commitment of the user, and as a private input for zero-knowledge proof generation. The secret hash should be kept private by the user. |
| **Identity commitment** | Hash obtained from the `Identity secret hash` by using the poseidon hash function. It is used by the users for registering in the protocol. |
| **Signal** | The message generated by a user. It is an arbitrary bit string that may represent a chat message, a URL request, protobuf message, etc. |
| **Signal hash** | Keccak256 hash of the signal modulo circuit's field characteristic, used as an input in the RLN circuit. |
@@ -310,7 +345,7 @@ which together with the ZK-SNARK circuit enable the above mentioned features.
| **Merkle proof** | Proof that a user is member of the RLN membership tree. |
### RLN ZK-Circuit specific terms
#### RLN Zero-Knowledge Circuit specific terms
| Term | Description |
|---------------------------|-------------------------------------------------------------------------------------|
@@ -321,30 +356,27 @@ which together with the ZK-SNARK circuit enable the above mentioned features.
| **External nullifier** | Poseidon hash of [Epoch, RLN Identifier]. An identifier that groups signals and can be thought of as a voting booth. |
| **Internal nullifier** | Poseidon hash of [A1]. This field ensures that a user can send only one valid signal per external nullifier without risking being slashed. Public input of the circuit. |
### ZK Circuits specification
#### Zero-Knowledge Circuits specification
Anonymous signaling with a controlled rate limit is enabled by proving that the user is part of a group which has high barriers to entry (form of stake) and
enabling secret reveal if more than 1 unique signal is produced per external nullifier.
The membership part is implemented using membership [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree) and Merkle proofs,
The membership part is implemented using membership [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree) and Merkle proofs,
while the secret reveal part is enabled by using the Shamir's Secret Sharing scheme.
Essentially the protocol requires the users to generate zero-knowledge proof to be able to send signals and participate in the application.
Essentially the protocol requires the users to generate zero-knowledge proof to be able to send signals and
participate in the application.
The zero knowledge proof proves that the user is member of a group,
but also enforces the user to share part of their secret for each signal in an external nullifier.
The external nullifier is usually represented by timestamp or a time interval.
It can also be thought of as a voting booth in voting applications.
The ZK Circuit is implemented using a [Groth-16 ZK-SNARK](https://eprint.iacr.org/2016/260.pdf),
The zero-knowledge Circuit is implemented using a [Groth-16 ZK-SNARK](https://eprint.iacr.org/2016/260.pdf),
using the [circomlib](https://docs.circom.io/) library.
#### System parameters
##### System parameters
- `DEPTH` - Merkle tree depth
#### Circuit parameters
##### Circuit parameters
**Public Inputs**
- `x`
@@ -360,7 +392,7 @@ using the [circomlib](https://docs.circom.io/) library.
- `root` - the rln membership tree root
- `internal_nullifier`
#### Hash function
##### Hash function
Canonical [Poseidon hash implementation](https://eprint.iacr.org/2019/458.pdf) is used,
as implemented in the [circomlib library](https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom), according to the Poseidon paper.
@@ -377,54 +409,59 @@ This Poseidon hash version (canonical implementation) uses the following paramet
|7 | 8 | 8 | 64|
|8 | 9 | 8 | 63|
##### Membership implementation
#### Membership implementation
For a valid signal, a user's `identity_commitment` (more on identity commitments below) must exist in identity membership tree.
For a valid signal, a user's `identity_commitment`
(more on identity commitments below) must exist in identity membership tree.
Membership is proven by providing a membership proof (witness).
The fields from the membership proof required for the verification are:
The fields from the membership proof REQUIRED for the verification are:
`path_elements` and `identity_path_index`.
[IncrementalQuinTree](https://github.com/appliedzkp/incrementalquintree) algorithm is used for constructing the Membership Merkle tree.
The circuits are reused from this repository.
You can find out more details about the IncrementalQuinTree algorithm [here](https://ethresear.ch/t/gas-and-circuit-constraint-benchmarks-of-binary-and-quinary-incremental-Merkle-trees-using-the-poseidon-hash-function/7446).
### Slashing and Shamir's Secret Sharing
#### Slashing and Shamir's Secret Sharing
Slashing is enabled by using polynomials and [Shamir's Secret sharing](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing).
In order to produce a valid proof, `identity_secret_hash` as a private input to the circuit.
Then a secret equation is created in the form of:
```
y = a_0 + x * a_1,
```js
y = a_0 + x * a_1;
```
where `a_0` is the `identity_secret_hash` and `a_1 = hash(a_0, external nullifier)`.
Along with the generated proof,
the users need to provide a `(x, y)` share which satisfies the line equation,
the users MUST provide a `(x, y)` share which satisfies the line equation,
in order for their proof to be verified.
`x` is the hashed signal, while the `y` is the circuit output.
With more than one pair of unique shares, anyone can derive `a_0`, i.e. the `identity_secret_hash` .
With more than one pair of unique shares, anyone can derive `a_0`, i.e. the `identity_secret_hash`.
The hash of a signal will be the evaluation point `x`.
In this way, a member who sends more than one unique signal per `external_nullifier` risks their identity secret being revealed.
In this way,
a member who sends more than one unique signal per `external_nullifier` risks their identity secret being revealed.
Note that shares used in different epochs and different RLN apps cannot be used to derive the identity secret hash.
Note that shares used in different epochs and
different RLN apps cannot be used to derive the `identity_secret_hash`.
Thanks to the `external_nullifier` definition, also shares computed from same secret within same epoch but in different RLN apps cannot be used to derive the identity secret hash.
The `rln_identifier` is a random value from a finite field,
unique per RLN app,
and is used for additional cross-application security - to protect the user secrets being compromised if they use the same credentials accross different RLN apps.
The `rln_identifier` is a random value from a finite field, unique per RLN app,
and is used for additional cross-application security -
to protect the user secrets being compromised if they use the same credentials accross different RLN apps.
If `rln_identifier` is not present,
the user uses the same credentials and sends a different message for two different RLN apps using the same `external_nullifier`,
the user uses the same credentials and
sends a different message for two different RLN apps using the same `external_nullifier`,
then their user signals can be grouped by the `internal_nullifier` which could lead the user's secret revealed.
This is because two separate signals under the same `internal_nullifier` can be treated as rate limiting violation.
With adding the `rln_identifier` field we obscure the `internal_nullifier`,
so this kind of attack can be hardened because we don't have the same `internal_nullifier` anymore.
### Identity credentials generation
#### Identity credentials generation
In order to be able to generate valid proofs, the users need to be part of the identity membership Merkle tree.
In order to be able to generate valid proofs, the users MUST be part of the identity membership Merkle tree.
They are part of the identity membership Merkle tree if their `identity_commitment` is placed in a leaf in the tree.
The identity credentials of a user are composed of:
@@ -433,132 +470,146 @@ The identity credentials of a user are composed of:
- `identity_secret_hash`
- `identity_commitment`
#### `identity_secret`
##### `identity_secret`
The `identity_secret` is generated in the following way:
```
identity_nullifier = random_32_byte_buffer
identity_trapdoor = random_32_byte_buffer
identity_secret = [identity_nullifier, identity_trapdoor]
```js
identity_nullifier = random_32_byte_buffer;
identity_trapdoor = random_32_byte_buffer;
identity_secret = [identity_nullifier, identity_trapdoor];
```
The same secret should not be used accross different protocols,
The same secret SHOULD NOT be used accross different protocols,
because revealing the secret at one protocol could break privacy for the user in the other protocols.
#### `identity_secret_hash`
##### `identity_secret_hash`
The `identity_secret_hash` is generated by obtaining a Poseidon hash of the `identity_secret` array:
```
identity_secret_hash = poseidonHash(identity_secret)
```js
identity_secret_hash = poseidonHash(identity_secret);
```
#### `identity_commitment`
##### `identity_commitment`
The `identity_commitment` is generated by obtaining a Poseidon hash of the `identity_secret_hash`:
```
identity_commitment = poseidonHash([identity_secret_hash])
```js
identity_commitment = poseidonHash([identity_secret_hash]);
```
### Appendix A: Security Considerations
## Appendix A: Security considerations
RLN is an experimental and still un-audited technology. This means that the circuits have not been yet audited.
RLN is an experimental and still un-audited technology.
This means that the circuits have not been yet audited.
Another consideration is the security of the underlying primitives.
zk-SNARKS require a trusted setup for generating a prover and verifier keys.
The standard for this is to use trusted [Multi-Party Computation (MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation) ceremony,
which requires two phases.
Trusted MPC ceremony has not yet been performed for the RLN circuits.
### SSS security assumptions
#### SSS Security Assumptions
Shamir-Secret Sharing requires polynomial coefficients to be independent of each other.
However, `a_1` depends on `a_0` through the Poseidon hash algorithm.
Due to the design of Poseidon, it is possible to [attack](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627) the protocol.
It was decided *not* to change the circuits design, since at the moment the attack is infeasible. Therefore, implementers must be aware that the current version provides approximately 160-bit security and not 254.
Due to the design of Poseidon,
it is possible to [attack](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627) the protocol.
It was decided *not* to change the circuits design, since at the moment the attack is infeasible.
Therefore, implementers must be aware that the current version provides approximately 160-bit security and not 254.
Possible improvements:
* [change the circuit](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627) to make coefficients independent;
* switch to other hash function (Keccak, SHA);
## Appendix B: Identity scheme choice
### Appendix B: Identity Scheme Choice
The hashing scheme used is based on the design decisions which also include the Semaphore circuits.
Our goal was to ensure compatibility of the secrets for apps that use Semaphore and
RLN circuits while also not compromising on security because of using the same secrets.
For example let's say there is a voting app that uses Semaphore,
For example, let's say there is a voting app that uses Semaphore,
and also a chat app that uses RLN.
The UX would be better if the users would not need to care about complicated identity management (secrets and commitments) t
hey use for each app, and it would be much better if they could use a single id commitment for this.
The UX would be better if the users would not need to care about complicated identity management
(secrets and commitments) they use for each app,
and it would be much better if they could use a single id commitment for this.
Also in some cases these kind of dependency is required -
RLN chat app using Interep as a registry (instead of using financial stake).
One potential concern about this interoperability is a slashed user on the RLN app side
having their security compromised on the semaphore side apps as well.
I.e obtaining the user's secret, anyone would be able to generate valid semaphore proofs as the slashed user.
We don't want that, and we should keep user's app specific security threats in the domain of that app alone.
I.e obtaining the user's secret,
anyone would be able to generate valid semaphore proofs as the slashed user.
We don't want that,
and we should keep user's app specific security threats in the domain of that app alone.
To achieve the above interoperability UX while preventing the shared app security model
(i.e slashing user on an RLN app having impact on Semaphore apps),
we had to do the follow in regard the identity secret and identity commitment:
```
identity_secret = [identity_nullifier, identity_trapdoor]
identity_secret_hash = poseidonHash(identity_secret)
identity_commitment = poseidonHash([identity_secret_hash])
```js
identity_secret = [identity_nullifier, identity_trapdoor];
identity_secret_hash = poseidonHash(identity_secret);
identity_commitment = poseidonHash([identity_secret_hash]);
```
Secret components for generating Semaphore proof:
```
identity_nullifier
identity_trapdoor
```
- `identity_nullifier`
- `identity_trapdoor`
Secret components for generting RLN proof:
```
identity_secret_hash
```
- `identity_secret_hash`
When a user is slashed on the RLN app side, their identity secret hash is revealed.
However a semaphore proof can't be generated because we do not know the user's nullifier and trapdoor.
When a user is slashed on the RLN app side, their `identity_secret_hash` is revealed.
However, a semaphore proof can't be generated because
we do not know the user's `identity_nullifier` and `identity_trapdoor`.
With this design we achieve:
identity commitment (Semaphore) == identity commitment (RLN)
`identity_commitment` (Semaphore) == `identity_commitment` (RLN)
secret (semaphore) != secret (RLN).
This is the only option we had for the scheme in order to satisfy the properties described above.
Also for RLN we do a single secret component input for the circuit.
Also, for RLN we do a single secret component input for the circuit.
Thus we need to hash the secret array (two components) to a secret hash,
and we use that as a secret component input.
## Appendix C: Auxiliary tooling
### Appendix C: Auxiliary Tooling
There are few additional tools implemented for easier integrations and usage of the RLN protocol.
[`zerokit`](https://github.com/vacp2p/zerokit) is a set of Zero Knowledge modules, written in Rust and designed to be used in many different environments.
[`zerokit`](https://github.com/vacp2p/zerokit) is a set of Zero Knowledge modules,
written in Rust and designed to be used in many different environments.
Among different modules, it supports `Semaphore` and `RLN`.
[`zk-kit`](https://github.com/appliedzkp/zk-kit) is a typescript library which exposes APIs for identity credentials generation,
as well as proof generation.
It supports various protocols (`Semaphore`, `RLN`).
[`zk-keeper`](https://github.com/akinovak/zk-keeper) is a browser plugin which allows for safe credential storing and proof generation.
You can think of MetaMask for ZK-Proofs.
[`zk-keeper`](https://github.com/akinovak/zk-keeper) is a browser plugin which allows for safe credential storing and
proof generation.
You can think of MetaMask for zero-knowledge proofs.
It uses `zk-kit` under the hood.
## Appendix D: Example usage
### Appendix D: Example Usage
The following examples are code snippets using the `zerokit` RLN module.
The examples are written in [rust](https://www.rust-lang.org/).
### Creating a RLN object
#### Creating a RLN Object
```rust
use rln::protocol::*;
use rln::public::*;
use std::io::Cursor;
@@ -569,42 +620,50 @@ let tree_height = 20;
let resources = Cursor::new("../zerokit/rln/resources/tree_height_20/");
// We create a new RLN instance
let mut rln = RLN::new(tree_height, resources);
```
### Generating identity credentials
#### Generating Identity Credentials
```rust
// We generate an identity tuple
let mut buffer = Cursor::new(Vec::<u8>::new());
rln.extended_key_gen(&mut buffer).unwrap();
// We deserialize the keygen output to obtain
// the identiy_secret and id_commitment
let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) = deserialize_identity_tuple(buffer.into_inner());
```
### Adding ID commitment to the RLN Merkle tree
#### Adding ID Commitment to the RLN Merkle Tree
```rust
// We define the tree index where id_commitment will be added
let id_index = 10;
// We serialize id_commitment and pass it to set_leaf
let mut buffer = Cursor::new(serialize_field_element(id_commitment));
rln.set_leaf(id_index, &mut buffer).unwrap();
```
### Setting epoch and signal
#### Setting Epoch and Signal
```rust
// We generate epoch from a date seed and we ensure is
// mapped to a field element by hashing-to-field its content
let epoch = hash_to_field(b"Today at noon, this year");
// We set our signal
let signal = b"RLN is awesome";
```
### Generating proof
#### Generating Proof
```rust
// We prepare input to the proof generation routine
let proof_input = prepare_prove_input(identity_secret, id_index, epoch, signal);
// We generate a RLN proof for proof_input
@@ -614,18 +673,21 @@ rln.generate_rln_proof(&mut in_buffer, &mut out_buffer)
.unwrap();
// We get the public outputs returned by the circuit evaluation
let proof_data = out_buffer.into_inner();
```
### Verifiying proof
#### Verifiying Proof
```rust
// We prepare input to the proof verification routine
let verify_data = prepare_verify_input(proof_data, signal);
// We verify the zk-proof against the provided proof values
// We verify the zero-knowledge proof against the provided proof values
let mut in_buffer = Cursor::new(verify_data);
let verified = rln.verify(&mut in_buffer).unwrap();
// We ensure the proof is valid
assert!(verified);
```
For more details please visit the [`zerokit`](https://github.com/vacp2p/zerokit) library.
@@ -636,17 +698,28 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
## References
- [17/WAKU2-RLN-RELAY RFC](../../waku/standards/core/17/rln-relay.md)
- [Interep](https://interep.link/)
- [incremental Merkle tree algorithm](https://github.com/appliedzkp/incrementalquintree/blob/master/ts/IncrementalQuinTree.ts)
- [Shamir's Secret sharing scheme](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing)
- [Lagrange polynomials](https://en.wikipedia.org/wiki/Lagrange_polynomial)
- [ZK-SNARK](https://z.cash/technology/zksnarks/)
- [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree)
- [Groth-16 ZK-SNARK](https://eprint.iacr.org/2016/260.pdf)
- [circomlib](https://docs.circom.io/)
- [Poseidon hash implementation](https://eprint.iacr.org/2019/458.pdf)
- [circomlib library](https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom)
- [IncrementalQuinTree](https://github.com/appliedzkp/incrementalquintree)
- [IncrementalQuinTree algorithm](https://ethresear.ch/t/gas-and-circuit-constraint-benchmarks-of-binary-and-quinary-incremental-Merkle-trees-using-the-poseidon-hash-function/7446)
- [Multi-Party Computation (MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation)
- [Poseidon hash attack](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627)
- [zerokit](https://github.com/vacp2p/zerokit)
- [zk-kit](https://github.com/appliedzkp/zk-kit)
- [zk-keeper](https://github.com/akinovak/zk-keeper)
- [rust](https://www.rust-lang.org/)
### Informative
- [1] https://medium.com/privacy-scaling-explorations/rate-limiting-nullifier-a-spam-protection-mechanism-for-anonymous-environments-bbe4006a57d
- [2] https://github.com/appliedzkp/zk-kit
- [3] https://github.com/akinovak/zk-keeper
- [4] https://z.cash/technology/zksnarks/
- [5] https://en.wikipedia.org/wiki/Merkle_tree
- [6] https://eprint.iacr.org/2016/260.pdf
- [7] https://docs.circom.io/
- [8] https://eprint.iacr.org/2019/458.pdf
- [9] https://github.com/appliedzkp/incrementalquintree
- [10] https://ethresear.ch/t/gas-and-circuit-constraint-benchmarks-of-binary-and-quinary-incremental-merkle-trees-using-the-poseidon-hash-function/7446
- [11] https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
- [12] https://research.nccgroup.com/2020/06/24/security-considerations-of-zk-snark-parameter-multi-party-computation/
- [13] https://github.com/Rate-Limiting-Nullifier/rln-circuits/
- [14] https://rate-limiting-nullifier.github.io/rln-docs/
- [2] https://research.nccgroup.com/2020/06/24/security-considerations-of-zk-snark-parameter-multi-party-computation/
- [3] https://github.com/Rate-Limiting-Nullifier/rln-circuits/
- [4] https://rate-limiting-nullifier.github.io/rln-docs/

View File

@@ -0,0 +1,732 @@
---
title: VAC-DECENTRALIZED-MESSAGING-ETHEREUM
name: Decentralized Key and Session Setup for Secure Messaging over Ethereum
status: raw
category: informational
editor: Ramses Fernandez-Valencia <ramses@status.im>
contributors:
---
## Abstract
This document introduces a decentralized group messaging protocol using Ethereum adresses as identifiers.
It is based in the proposal [DCGKA](https://eprint.iacr.org/2020/1281) by Weidner et al.
It includes also approximations to overcome limitations related to using PKI and the multi-device setting.
## Motivation
The need for secure communications has become paramount.
Traditional centralized messaging protocols are susceptible to various security threats,
including unauthorized access, data breaches, and single points of failure.
Therefore a decentralized approach to secure communication becomes increasingly relevant,
offering a robust solution to address these challenges.
Secure messaging protocols used should have the following key features:
1. **Asynchronous Messaging:** Users can send messages even if the recipients are not online at the moment.
2. **Resilience to Compromise:** If a user's security is compromised,
the protocol ensures that previous messages remain secure through forward secrecy (FS).
This means that messages sent before the compromise cannot be decrypted by adversaries.
Additionally, the protocol maintains post-compromise security (PCS) by regularly updating keys,
making it difficult for adversaries to decrypt future communication.
3. **Dynamic Group Management:** Users can easily add or remove group members at any time,
reflecting the flexible nature of communication within the app.
In this field, there exists a *trilemma*, similar to what one observes in blockchain,
involving three key aspects:
1. security,
2. scalability, and
3. decentralization.
For instance, protocols like the [MLS](https://messaginglayersecurity.rocks) perform well in terms of scalability and security.
However, they falls short in decentralization.
Newer studies such as [CoCoa](https://eprint.iacr.org/2022/251) improve features related to security and scalability,
but they still rely on servers, which may not be fully trusted though they are necessary.
On the other hand,
older studies like [Causal TreeKEM](https://mattweidner.com/assets/pdf/acs-dissertation.pdf) exhibit decent scalability (logarithmic)
but lack forward secrecy and have weak post-compromise security (PCS).
The creators of [DCGKA](https://eprint.iacr.org/2020/1281) introduce a decentralized,
asynchronous secure group messaging protocol that supports dynamic groups.
This protocol operates effectively on various underlying networks without strict requirements on message ordering or latency.
It can be implemented in peer-to-peer or anonymity networks,
accommodating network partitions, high latency links, and disconnected operation seamlessly.
Notably, the protocol doesn't rely on servers or
a consensus protocol for its functionality.
This proposal provides end-to-end encryption with forward secrecy and post-compromise security,
even when multiple users concurrently modify the group state.
## Theory
### Protocol overview
This protocol makes use of ratchets to provide FS by encrypting each message with a different key.
In the figure one can see the ratchet for encrypting a sequence of messages.
The sender requires an initial update secret `I_1`, which is introduced in a PRG.
The PRG will produce two outputs, namely a symmetric key for AEAD encryption, and
a seed for the next ratchet state.
The associated data needed in the AEAD encryption includes the message index `i`.
The ciphertext `c_i` associated to message `m_i` is then broadcasted to all group members.
The next step requires deleting `I_1`, `k_i` and any old ratchet state.
After a period of time the sender may replace the ratchet state with new update secrets `I_2`, `I_3`, and so on.
To start a post-compromise security update,
a user creates a new random value known as a seed secret and
shares it with every other group member through a secure two-party channel.
Upon receiving the seed secret,
each group member uses it to calculate an update secret for both the sender's ratchet and their own.
Additionally, the recipient sends an unencrypted acknowledgment to the group confirming the update.
Every member who receives the acknowledgment updates not only the ratchet for the original sender but
also the ratchet for the sender of the acknowledgment.
Consequently, after sharing the seed secret through `n - 1` two-party messages and
confirming it with `n - 1` broadcast acknowledgments,
every group member has derived an update secret and updated their ratchet accordingly.
When removing a group member,
the user who initiates the removal conducts a post-compromise security update
by sending the update secret to all group members except the one being removed.
To add a new group member,
each existing group member shares the necessary state with the new user,
enabling them to derive their future update secrets.
Since group members may receive messages in various orders,
it's important to ensure that each sender's ratchet is updated consistently
with the same sequence of update secrets at each group member.
The network protocol used in this scheme ensures that messages from the same sender are processed in the order they were sent.
### Components of the protocol
This protocol relies in 3 components:
authenticated causal broadcast (ACB),
decentralized group membership (DGM) and
2-party secure messaging (2SM).
#### Authenticated causal broadcast
A causal order is a partial order relation `<` on messages.
Two messages `m_1` and `m_2` are causally ordered, or
`m_1` causally precedes `m_2`
(denoted by `m_1 < m_2`), if one of the following contiditions hold:
1. `m_1` and `m_2` were sent by the same group member, and `m_1` was sent before `m_2`.
2. `m_2` was sent by a group member U, and `m_1` was received and
processed by `U` before sending `m_2`.
3. There exists `m_3` such that `m_1 < m_3` and `m_3 < m_2`.
Causal broadcast requires that before processing `m`,
a group member must process all preceding messages `{m' | m' < m}`.
The causal broadcast module used in this protocol authenticates the sender of each message,
as well as its causal ordering metadata, using a digital signature under the senders identity key.
This prevents a passive adversary from impersonating users or affecting causally ordered delivery.
#### Decentralized group membership
This protocol assumes the existence of a decentralized group membership function (denoted as DGM)
that takes a set of membership change messages and their causal order relantionships,
and returns the current set of group members IDs.
It needs to be deterministic and depend only on causal order, and not exact order.
#### 2-party secure messaging (2SM)
This protocol makes use of bidirectional 2-party secure messaging schemes,
which consist of 3 algorithms: `2SM-Init`, `2SM-Send` and `2SM-Receive`.
##### 2SM-Init
This function takes two IDs as inputs:
`ID1` representing the local user and `ID2` representing the other party.
It returns an initial protocol state `sigma`.
The 2SM protocol relies on a Public Key Infrastructure (PKI) or
a key server to map these IDs to their corresponding public keys.
In practice, the PKI should incorporate ephemeral prekeys.
This allows users to send messages to a new group member,
even if that member is currently offline.
##### 2SM-Send
This function takes a state `sigma` and a plaintext `m` as inputs, and
returns a new state `sigma` and a ciphertext `c`.
##### 2SM-Receive
This function takes a state `sigma` and a ciphertext `c`, and
returns a new state `sigma` and a plaintext `m`.
#### 2SM Syntax
The variable `sigma` denotes the state consisting in the variables below:
```
sigma.mySks[0] = sk
sigma.nextIndex = 1
sigma.receivedSk = empty_string
sigma.otherPk = pk`<br>
sigma.otherPksender = “other”
sigma.otherPkIndex = 0
```
#### 2SM-Init
On input a key pair `(sk, pk)`, this functions otuputs a state `sigma`.
#### 2SM-Send
This function encrypts the message `m` using `sigma.otherPk`,
which represents the other partys current public key.
This key is determined based on the last public key generated for the other party or
the last public key received from the other party,
whichever is more recent.
`sigma.otherPkSender` is set to `me` in the former case and `other` in the latter case.
Metadata including `otherPkSender` and
`otherPkIndex` are included in the message to indicate which of the recipients public keys is being utilized.
Additionally, this function generates a new key pair for the local user,
storing the secret key in `sigma.mySks` and sending the public key.
Similarly, it generates a new key pair for the other party,
sending the secret key (encrypted) and storing the public key in `sigma.otherPk`.
```
sigma.mySks[sigma.nextIndex], myNewPk) = PKE-Gen()
(otherNewSk, otherNewPk) = PKE-Gen()
plaintext = (m, otherNewSk, sigma`.nextIndex, myNewPk)
msg = (PKE-Enc(sigma.otherPk, plaintext), sigma.otherPkSender, sigma.otherPkIndex)
sigma.nextIndex++
(sigma.otherPk, sigma.otherPkSender, sigma.otherPkIndex) = (otherNewPk, "me", empty_string)
return (sigma`, msg)
```
#### 2SM-Receive
This function utilizes the metadata of the message `c` to determine which secret key to utilize for decryption,
assigning it to `sk`.
If the secret key corresponds to one generated by ourselves,
that secret key along with all keys with lower index are deleted.
This deletion is indicated by `sigma.mySks[≤ keyIndex] = empty_string`.
Subsequently, the new public and secret keys contained in the message are stored.
```
(ciphertext, keySender, keyIndex) = c
if keySender = "other" then
sk = sigma.mySks[keyIndex]
sigma.mySks[≤ keyIndex] = empty_string
else sk = sigma.receivedSk
(m, sigma.receivedSk, sigma.otherPkIndex, sigma.otherPk) = PKE-Dec(sk, ciphertext)
sigma.otherPkSender = "other"
return (sigma, m)
```
### PKE Syntax
The required PKE that MUST be used is ElGamal with a 2048-bit modulus `p`.
#### Parameters
The following parameters must be used:
```
p = 308920927247127345254346920820166145569
g = 2
```
#### PKE-KGen
Each user `u` MUST do the following:
```
PKE-KGen():
a = randint(2, p-2)
pk = (p, g, g^a)
sk = a
return (pk, sk)
```
#### PKE-Enc
A user `v` encrypting a message `m` for `u` MUST follow these steps:
```
PKE-Enc(pk):
k = randint(2, p-2)
eta = g^k % p
delta = m * (g^a)^k % p
return ((eta, delta))
```
#### PKE-Dec
The user `u` recovers a message `m` from a ciphertext `c` by performing the following operations:
```
PKE-Dec(sk):
mu = eta^(p-1-sk) % p
return ((mu * delta) % p)
```
### DCGKA Syntax
#### Auxiliary functions
There exist 6 functions that are auxiliary for the rest of components of the protocol, namely:
#### init
This function takes an `ID` as input and returns its associated initial state, denoted by `gamma`:
```
gamma.myId = ID
gamma.mySeq = 0
gamma.history = empty
gamma.nextSeed = empty_string
gamma.2sm[·] = empty_string
gamma.memberSecret[·, ·, ·] = empty_string
gamma.ratchet[·] = empty_string
return (gamma)
```
#### encrypt-to
Upon reception of the recipients `ID` and a plaintext,
it encrypts a direct message for another group member.
Should it be the first message for a particular `ID`,
then the `2SM` protocol state is initialized and stored in `gamma.2sm[recipient.ID]`.
One then uses `2SM_Send` to encrypt the message and store the updated protocol in `gamma`.
```
if gamma.2sm[recipient_ID] = empty_string then
gamma.2sm[recipient_ID] = 2SM_Init(gamma.myID, recipient_ID)
(gamma.2sm[recipient_ID], ciphertext) = 2SM_Send(gamma.2sm[recipient_ID], plaintext)
return (gamma, ciphertext)
```
#### decrypt-from
After receiving the senders `ID` and a ciphertext,
it behaves as the reverse function of `encrypt-to` and has a similar initialization:
```
if gamma.2sm[sender_ID] = empty_string then
gamma.2sm[sender_ID] = 2SM_Init(gamma.myID, sender_ID)
(gamma.2sm[sender_ID], plaintext) = 2SM_Receive(gamma.2sm[sender_ID], ciphertext)
return (gamma, plaintext)
```
#### update-ratchet
This function generates the next update secret `I_update` for the group member `ID`.
The ratchet state is stored in `gamma.ratchet[ID]`.
It is required to use a HMAC-based key derivation function HKDF to combine the ratchet state with an input,
returning an update secret and a new ratchet state.
```
(updateSecret, gamma.ratchet[ID]) = HKDF(gamma.ratchet[ID], input)
return (gamma, updateSecret)
```
#### member-view
This function calculates the set of group members based on the most recent control message sent by the specified user `ID`.
It filters the group membership operations to include only those observed by the specified `ID`, and
then invokes the DGM function to generate the group membership.
```
ops = {m in gamma.history st. m was sent or acknowledged by ID}
return DGM(ops)
```
#### generate-seed
This functions generates a random bit string and
sends it encrypted to each member of the group using the `2SM` mechanism.
It returns the updated protocol state and
the set of direct messages (denoted as `dmsgs`) to send.
```
gamma.nextSeed = random.randbytes()
dmsgs = empty
for each ID in recipients:
(gamma, msg) = encrypt-to(gamma, ID, gamma.nextSeed)
dmsgs = dmsgs + (ID, msg)
return (gamma, dmsgs)
```
### Creation of a group
A group is generated in a 3 steps procedure:
1. A user calls the `create` function and broadcasts a control message of type *create*.
2. Each receiver of the message processes the message and broadcasts an *ack* control message.
3. Each member processes the *ack* message received.
#### create
This function generates a *create* control message and
calls `generate-seed` to define the set of direct messages that need to be sent.
Then it calls `process-create` to process the control message for this user.
The function `process-create` returns a tuple including an updated state gamma and
an update secret `I`.
```
control = (“create”, gamma.mySeq, IDs)
(gamma, dmsgs) = generate-seed(gamma, IDs)
(gamma, _, _, I, _) = process-create(gamma, gamma.myId, gamma.mySeq, IDs, empty_string)
return (gamma, control, dmsgs, I)
```
#### process-seed
This function initially employs `member-view` to identify the users who were part of the group when the control message was dispatched.
Then, it attempts to acquire the seed secret through the following steps:
1. If the control message was dispatched by the local user,
it uses the most recent invocation of `generate-seed` stored the seed secret in `gamma.nextSeed`.
2. If the `control` message was dispatched by another user, and
the local user is among its recipients,
the function utilizes `decrypt-from` to decrypt the direct message that includes the seed secret.
3. Otherwise, it returns an `ack` message without deriving an update secret.
Afterwards, `process-seed` generates separate member secrets for each group member from the seed secret by combining the seed secret and
each user ID using HKDF.
The secret for the sender of the message is stored in `senderSecret`,
while those for the other group members are stored in `gamma.memberSecret`.
The sender's member secret is immediately utilized to update their KDF ratchet and
compute their update secret `I_sender` using `update-ratchet`.
If the local user is the sender of the control message,
the process is completed, and the update secret is returned.
However, if the seed secret is received from another user,
an `ack` control message is constructed for broadcast,
including the sender ID and sequence number of the message being acknowledged.
The final step computes an update secret `I_me` for the local user invoking the `process-ack` function.
```
recipients = member-view(gamma, sender) - {sender}
if sender = gamma.myId then seed = gamma.nextSeed; gamma.nextSeed = empty_string
else if gamma.myId in recipients then (gamma, seed) = decrypt-from(gamma, sender, dmsg)
else
return (gamma, (ack, ++gamma.mySeq, (sender, seq)), empty_string , empty_string , empty_string)
for ID in recipients do gamma.memberSecret[sender, seq, ID] = HKDF(seed, ID)
senderSecret = HKDF(seed, sender)
(gamma, I_sender) = update-ratchet(gamma, sender, senderSecret)
if sender = gamma.myId then return (gamma, empty_string , empty_string , I_sender, empty_string)
control = (ack, ++gamma.mySeq, (sender, seq))
members = member-view(gamma, gamma.myId)
forward = empty
for ID in {members - (recipients + {sender})}
s = gamma.memberSecret[sender, seq, gamma.myId]
(gamma, msg) = encrypt-to(gamma, ID, s)
forward = forward + {(ID, msg)}
(gamma, _, _, I_me, _) = process-ack(gamma, gamma.myId, gamma.mySeq, (sender, seq), empty_string)
return (gamma, control, forward, I_sender, I_me)
```
#### process-create
This function is called by the sender and each of the receivers of the `create` control message.
First, it records the information from the create message in the `gamma.history+ {op}`,
which is used to track group membership changes. Then, it proceeds to call `process-seed`.
```
op = (”create”, sender, seq, IDs)
gamma.history = gamma.history + {op}
return (process-seed(gamma, sender, seq, dmsg))
```
#### process-ack
This function is called by those group members once they receive an ack message.
In `process-ack`, `ackID` and `ackSeq` are the sender and
sequence number of the acknowledged message.
Firstly, if the acknowledged message is a group membership operation,
it records the acknowledgement in `gamma.history`.
Following this, the function retrieves the relevant member secret from `gamma.memberSecret`,
which was previously obtained from the seed secret contained in the acknowledged message.
Finally, it updates the ratchet for the sender of the `ack` and
returns the resulting update secret.
```
if (ackID, ackSeq) was a create / add / remove then
op = ("ack", sender, seq, ackID, ackSeq)
gamma.history = gamma.history + {op}`
s = gamma.memberSecret[ackID, ackSeq, sender]
gamma.memberSecret[ackID, ackSeq, sender] = empty_string
if (s = empty_string) & (dmsg = empty_string) then return (gamma, empty_string, empty_string, empty_string, empty_string)
if (s = empty_string) then (gamma, s) = decrypt-from(gamma, sender, dmsg)
(gamma, I) = update-ratchet(gamma, sender, s)
return (gamma, empty_string, empty_string, I, empty_string)
```
The HKDF function MUST follow RFC 5869 using the hash function SHA256.
### Post-compromise security updates and group member removal
The functions `update` and `remove` share similarities with `create`:
they both call the function `generate-seed` to encrypt a new seed secret for each group member.
The distinction lies in the determination of the group members using `member-view`.
In the case of `remove`, the user being removed is excluded from the recipients of the seed secret.
Additionally, the control message they construct is designated with type `update` or `remove` respectively.
Likewise, `process-update` and `process-remove` are akin to `process-create`.
The function `process-update` skips the update of `gamma.history`,
whereas `process-remove` includes a removal operation in the history.
#### update
```
control = ("update", ++gamma.mySeq, empty_string)
recipients = member-view(gamma, gamma.myId) - {gamma.myId}
(gamma, dmsgs) = generate-seed(gamma, recipients)
(gamma, _, _, I , _) = process-update(gamma, gamma.myId, gamma.mySeq, empty_string, empty_string)
return (gamma, control, dmsgs, I)
```
#### remove
```
control = ("remove", ++gamma.mySeq, empty)
recipients = member-view(gamma, gamma.myId) - {ID, gamma.myId}
(gamma, dmsgs) = generate-seed(gamma, recipients)
(gamma, _, _, I , _) = process-update(gamma, gamma.myId, gamma.mySeq, ID, empty_string)
return (gamma, control, dmsgs, I)
```
#### process-update
`return process-seed(gamma, sender, seq, dmsg)`
#### process-remove
```
op = ("remove", sender, seq, removed)
gamma.history = gamma.history + {op}
return process-seed(gamma, sender, seq, dmsg)
```
### Group member addition
#### add
When adding a new group member,
an existing member initiates the process by invoking the `add` function and
providing the ID of the user to be added.
This function prepares a control message marked as `add` for broadcast to the group.
Simultaneously, it creates a welcome message intended for the new member as a direct message.
This `welcome` message includes the current state of the sender's KDF ratchet,
encrypted using `2SM`, along with the history of group membership operations conducted so far.
```
control = ("add", ++gamma.mySeq, ID)
(gamma, c) = encrypt-to(gamma, ID, gamma.ratchet[gamma.myId])
op = ("add", gamma.myId, gamma.mySeq, ID)
welcome = (gamma.history + {op}, c)
(gamma, _, _, I, _) = process-add(gamma, gamma.myId, gamma.mySeq, ID, empty_string)
return (gamma, control, (ID, welcome), I)
```
#### process-add
This function is invoked by both the sender and
each recipient of an `add` message, which includes the new group member.
If the local user is the newly added member,
the function proceeds to call `process-welcome` and then exits.
Otherwise, it extends `gamma.history` with the `add` operation.
Line 5 determines whether the local user was already a group member at the time the `add` message was sent;
this condition is typically true but may be false if multiple users were added concurrently.
On lines 6 to 8, the ratchet for the sender of the *add* message is updated twice.
In both calls to `update-ratchet`,
a constant string is used as the ratchet input instead of a random seed secret.
The value returned by the first ratchet update is stored in `gamma.memberSecret` as the added users initial member secret.
The result of the second ratchet update becomes `I_sender`,
the update secret for the sender of the `add` message.
On line 10, if the local user is the sender, the update secret is returned.
If the local user is not the sender, an acknowledgment for the `add` message is required.
Therefore, on line 11, a control message of type `add-ack` is constructed for broadcast.
Subsequently, in line 12 the current ratchet state is encrypted using `2SM` to generate a direct message intended for the added user,
allowing them to decrypt subsequent messages sent by the sender.
Finally, in lines 13 to 15, `process-add-ack` is called to calculate the local users update secret (`I_me`),
which is then returned along with `I_sender`.
```
if added = gamma.myId then return process-welcome(gamma, sender, seq, dmsg)
op = ("add", sender, seq, added)
gamma.history = gamma.history + {op}
if gamma.myId in member-view(gamma, sender) then
(gamma, s) = update-ratchet(gamma, sender, "welcome")
gamma.memberSecret[sender, seq, added] = s
(gamma, I_sender) = update-ratchet(gamma, sender, "add")
else I_sender = empty_string
if sender = gamma.myId then return (gamma, empty_string, empty_string, I_sender, empty_string)
control = ("add-ack", ++gamma.mySeq, (sender, seq))
(gamma, c) = encrypt-to(gamma, added, ratchet[gamma.myId])
(gamma, _, _, I_me, _) = process-add-ack(gamma, gamma.myId, gamma.mySeq, (sender, seq), empty_string)
return (gamma, control, {(added, c)}, I_sender, I_me)
```
#### process-add-ack
This function is invoked by both the sender and each recipient of an `add-ack` message,
including the new group member.
Upon lines 12, the acknowledgment is added to `gamma.history`,
mirroring the process in `process-ack`.
If the current user is the new group member,
the `add-ack` message includes the direct message constructed in `process-add`;
this direct message contains the encrypted ratchet state of the sender of the `add-ack`,
then it is decrypted on lines 35.
Upon line 6, a check is performed to check if the local user was already a group member at the time the `add-ack` was sent.
If affirmative, a new update secret `I` for the sender of the `add-ack` is computed on line 7 by invoking `update-ratchet` with the constant string `add`.
In the scenario involving the new member,
the ratchet state was recently initialized on line 5.
This ratchet update facilitates all group members, including the new addition,
to derive each members update by obtaining any update secret from before their inclusion.
```
op = ("ack", sender, seq, ackID, ackSeq)
gamma$.history = gamma.history + {op}
if dmsg != empty_string then
(gamma, s) = decrypt-from(gamma, sender, dmsg)
gamma.ratchet[sender] = s
if gamma.myId in member-view(gamma, sender) then
(gamma, I) = update-ratchet(gamma, sender, "add")
return (gamma, empty_string, empty_string, I, empty_string)
else return (gamma, empty_string, empty_string, empty_string, empty_string)
```
#### process-welcome
This function serves as the second step called by a newly added group member.
In this context, `adderHistory` represents the adding users copy of `gamma.history` sent in their welcome message,
which is utilized to initialize the added users history.
Here, `c` denotes the ciphertext of the adding users ratchet state,
which is decrypted on line 2 using `decrypt-from`.
Once `gamma.ratchet[sender]` is initialized,
`update-ratchet` is invoked twice on lines 3 to 5 with the constant strings `welcome` and `add` respectively.
These operations mirror the ratchet operations performed by every other group member in `process-add`.
The outcome of the first `update-ratchet` call becomes the first member secret for the added user,
while the second call returns `I_sender`, the update secret for the sender of the add operation.
Subsequently, the new group member constructs an *ack* control message to broadcast on line 6 and
calls `process-ack` to compute their initial update secret I_me.
The function `process-ack` reads from `gamma.memberSecret` and
passes it to `update-ratchet`.
The previous ratchet state for the new member is the empty string `empty`, as established by `init`,
thereby initializing the new members ratchet.
Upon receiving the new members `ack`,
every other group member initializes their copy of the new members ratchet in a similar manner.
By the conclusion of `process-welcome`,
the new group member has acquired update secrets for themselves and the user who added them.
The ratchets for other group members are initialized by `process-add-ack`.
```
gamma.history = adderHistory
(gamma, gamma.ratchet[sender]) = decrypt-from(gamma, sender, c)
(gamma, s) = update-ratchet(gamma, sender, "welcome")
gamma.memberSecret[sender, seq, gamma.myId] = s
(gamma, I_sender) = update-ratchet(gamma, sender, "add")
control = ("ack", ++gamma.mySeq, (sender, seq))
(gamma, _, _, I_me, _) = process-ack(gamma, gamma.myId, gamma.mySeq, (sender, seq), empty_string)
return (gamma, control, empty_string , I_sender, I_me)
```
## Privacy Considerations
### Dependency on PKI
The [DCGKA](https://eprint.iacr.org/2020/1281) proposal presents some limitations highlighted by the authors.
Among these limitations one finds the requirement of a PKI (or a key server) mapping IDs to public keys.
One method to overcome this limitation is adapting the protocol SIWE (Sign in with Ethereum) so
a user `u_1` who wants to start a communication with a user `u_2` can interact with latters wallet to request a public key using an Ethereum address as `ID`.
#### SIWE
The [SIWE](https://docs.login.xyz/general-information/siwe-overview) (Sign In With Ethereum) proposal was a suggested standard for leveraging Ethereum to authenticate and authorize users on web3 applications.
Its goal is to establish a standardized method for users to sign in to web3 applications using their Ethereum address and private key,
mirroring the process by which users currently sign in to web2 applications using their email and password.
Below follows the required steps:
1. A server generates a unique Nonce for each user intending to sign in.
2. A user initiates a request to connect to a website using their wallet.
3. The user is presented with a distinctive message that includes the Nonce and details about the website.
4. The user authenticates their identity by signing in with their wallet.
5. Upon successful authentication, the user's identity is confirmed or approved.
6. The website grants access to data specific to the authenticated user.
#### Our approach
The idea in the [DCGKA](https://eprint.iacr.org/2020/1281) setting closely resembles the procedure outlined in SIWE. Here:
1. The server corresponds to user D1,
who initiates a request (instead of generating a nonce) to obtain the public key of user D2.
2. Upon receiving the request, the wallet of D2 send the request to the user,
3. User D2 receives the request from the wallet, and decides whether accepts or rejects.
4. The wallet and responds with a message containing the requested public key in case of acceptance by D2.
This message may be signed, allowing D1 to verify that the owner of the received public key is indeed D2.
### Multi-device setting
One may see the set of devices as a group and create a group key for internal communications.
One may use treeKEM for instance,
since it provides interesting properties like forward secrecy and post-compromise security.
All devices share the same `ID`,
which is held by one of them, and from other users point of view, they would look as a single user.
Using servers, like in the paper [Multi-Device for Signal](https://eprint.iacr.org/2019/1363), should be avoided;
but this would imply using a particular device as receiver and broadcaster within the group.
There is an obvious drawback which is having a single device working as a “server”.
Should this device be attacked or without connection, there should be a mechanism for its revocation and replacement.
Another approach for communications between devices could be using the keypair of each device.
This could open the door to use UPKE, since keypairs should be regenerated frequently.
Each time a device sends a message, either an internal message or an external message,
it needs to replicate and broadcast it to all devices in the group.
The mechanism for the substitution of misbehaving leader devices follows:
1. Each device within a group knows the details of other leader devices.
This information may come from metadata in received messages, and is replicated by the leader device.
2. To replace a leader, the user should select any other device within its group and
use it to send a signed message to all other users.
3. To get the ability to sign messages,
this new leader should request the keypair associated to the ID to the wallet.
4. Once the leader has been changed,
it revocates access from DCGKA to the former leader using the DCGKA protocol.
5. The new leader starts a key update in DCGKA.
Not all devices in a group should be able to send messages to other users.
Only the leader device should be in charge of sending and receiving messages.
To prevent other devices from sending messages outside their group, a requirement should be signing each message.
The keys associated to the `ID` should only be in control of the leader device.
The leader device is in charge of setting the keys involved in the DCGKA.
This information must be replicated within the group to make sure it is updated.
To detect missing messages or potential misbehavior, messages must include a counter.
### Using UPKE
Managing the group of devices of a user can be done either using a group key protocol such as treeKEM or
using the keypair of each device.
Setting a common key for a group of devices under the control of the same actor might be excessive,
furthermore it may imply some of the problems one can find in the usual setting of a group of different users;
for example: one of the devices may not participate in the required updating processes, representing a threat for the group.
The other approach to managing the group of devices is using each devices keypair,
but it would require each device updating these materia frequently, something that may not happens.
[UPKE](https://eprint.iacr.org/2022/068) is a form of asymetric cryptography
where any user can update any other users key pair by running an update algorithm with (high-entropy) private coins.
Any sender can initiate a *key update* by sending a special update ciphertext.
This ciphertext updates the receivers public key and also, once processed by the receiver, will update their secret key.
To the best of my knowledge,
there exists several efficient constructions both [UPKE from ElGamal](https://eprint.iacr.org/2019/1189) (based in the DH assumption) and
[UPKE from Lattices]((https://eprint.iacr.org/2023/1400)) (based in lattices).
None of them have been implemented in a secure messaging protocol, and this opens the door to some novel research.
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
- [DCGKA](https://eprint.iacr.org/2020/1281)
- [MLS](https://messaginglayersecurity.rocks)
- [CoCoa](https://eprint.iacr.org/2022/251)
- [Causal TreeKEM](https://mattweidner.com/assets/pdf/acs-dissertation.pdf)
- [SIWE](https://docs.login.xyz/general-information/siwe-overview)
- [Multi-device for Signal](https://eprint.iacr.org/2019/1363)
- [UPKE](https://eprint.iacr.org/2022/068)
- [UPKE from ElGamal](https://eprint.iacr.org/2019/1189)
- [UPKE from Lattices](https://eprint.iacr.org/2023/1400)

View File

@@ -1,6 +1,5 @@
---
slug: 70
title: 70/ETH-SECPM
title: ETH-SECPM
name: Secure channel setup using Ethereum accounts
status: raw
category: Standards Track
@@ -17,7 +16,7 @@ Therefore a decentralized approach to secure communication becomes increasingly
offering a robust solution to address these challenges.
This specification outlines a private messaging service using the Ethereum blockchain as authentication service.
Rooted in the existing [model](https://rfc.vac.dev/spec/20/),
Rooted in the existing [model](../../waku/standards/application/20/toy-eth-pm.md),
this proposal addresses the deficiencies related to forward privacy and authentication inherent in the current framework.
The specification is divided into 3 sections:
@@ -283,7 +282,11 @@ These identifiers MUST be computed according to Section 5.2 of [RFC9420](https:/
Each member of a group presents a credential that provides one or more identities for the member and associates them with the member's signing key.
The identities and signing key are verified by the Authentication Service in use for a group.
Credentials MUST follow the specifications of section 5.3 of [RFC9420](https://datatracker.ietf.org/doc/rfc9420/).
Credentials MUST follow the specifications of section 5.3 of [RFC9420](https://datatracker.ietf.org/doc/rfc9420/).
Below follows the flow diagram for the generation of credentials.
Users MUST generate key pairs by themselves.
![figure1](./images/eth-secpm_credential.png)
### Message framing
Handshake and application messages use a common framing structure providing encryption to ensure confidentiality within the group, and signing to authenticate the sender.
@@ -499,6 +502,11 @@ ProposalType proposal_types<V>;
CredentialType credential_types<V>;
}
```
The flow diagram shows the procedure to fetch key material from other users:
![figure2](./images/eth-secpm_fetching.png)
Below follows the flow diagram for the creation of a group:
![figure3](./images/eth-secpm_creation.png)
### Group evolution
Group membership can change, and existing members can change their keys in order to achieve post-compromise security.
@@ -543,6 +551,18 @@ The validation MUST be done according to one of the procedures described in Sect
When creating or processing a Commit, a client applies a list of proposals to the ratchet tree and `GroupContext`.
The client MUST apply the proposals in the list in the order described in Section 12.3 of [RFC9420](https://datatracker.ietf.org/doc/rfc9420/).
Below follows the flow diagram for the addition of a member to a group:
![figure4](./images/eth-secpm_add.png)
The diagram below shows the procedure to remove a group member:
<br>
![figure5](./images/eth-secpm_remove.png)
The flow diagram below shows an update procedure:
<br>
![figure6](./images/eth-secpm_update.png)
### Commit messages
Commit messages initiate new group epochs.
It informs group members to update their representation of the state of the group by applying the proposals and advancing the key schedule.
@@ -790,6 +810,20 @@ After successfully parsing the message into ABNF terms, translation MAY happen a
- The curve vurve448 MUST be chosen due to its higher security level: 224-bit security instead of the 128-bit security provided by X25519.
- It is important that Bob MUST NOT reuse `SPK`.
## Considerations related to the use of Ethereum addresses
### With respect to the Authentication Service
- If users used their Ethereum addresses as identifiers, they MUST generate their own credentials.
These credentials MUST use the digital signature key pair associated to the Ethereum address.
- Other users can verify credentials.
- With this approach, there is no need to have a dedicated Authentication Service responsible for the issuance and verification of credentials.
- The interaction diagram showing the generation of credentials becomes obsolete.
### With respect to the Delivery Service
- Users MUST generate their own KeyPackage.
- Other users can verify KeyPackages when required.
- A Delivery Service storage system MUST verify KeyPackages before storing them.
- Interaction diagrams involving the DS do not change.
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

View File

@@ -1,6 +1,5 @@
---
slug: 46
title: 46/GOSSIPSUB-TOR-PUSH
title: GOSSIPSUB-TOR-PUSH
name: Gossipsub Tor Push
status: raw
category: Standards Track

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

1
vac/raw/images/test.txt Normal file
View File

@@ -0,0 +1 @@

View File

@@ -1,6 +1,5 @@
---
slug: 48
title: 48/RLN-INTEREP-SPEC
title: RLN-INTEREP-SPEC
name: Interep as group management for RLN
status: raw
category:

View File

@@ -0,0 +1,105 @@
---
title: RLN-STEALTH-COMMITMENTS
name: RLN Stealth Commitment Usage
category: Standards Track
editor: Aaryamann Challani <aaryamann@status.im>
contributors:
- Jimmy Debe <jimmy@status.im>
---
## Abstract
This specification describes the usage of stealth commitments to add prospective users to a network-governed [32/RLN-V1](./32/rln-v1.md) membership set.
## Motivation
When [32/RLN-V1](./32/rln-v1.md) is enforced in [10/Waku2](../waku/standards/core/10/waku2.md),
all users are required to register to a membership set.
The membership set will store user identities allowing the secure interaction within an application.
Forcing a user to do an on-chain transaction to join a membership set is an onboarding friction,
and some projects may be opposed to this method.
To improve the user experience,
stealth commitments can be used by a counterparty to register identities on the user's behalf,
while maintaining the user's anonymity.
This document specifies a privacy-preserving mechanism,
allowing a counterparty to utilize [32/RLN-V1](./32/rln-v1.md) to register an `identityCommitment` on-chain.
Counterparties will be able to register members to a RLN membership set without exposing the user's private keys.
## Background
The [32/RLN-V1](./32/rln-v1.md) protocol,
consists of a smart contract that stores a `idenitityCommitment` in a membership set.
In order for a user to join the membership set,
the user is required to make a transaction on the blockchain.
A set of public keys is used to compute a stealth commitment for a user,
as described in [ERC-5564](https://eips.ethereum.org/EIPS/eip-5564).
This specification is an implementation of the [ERC-5564](https://eips.ethereum.org/EIPS/eip-5564) scheme,
tailored to the curve that is used in the [32/RLN-V1](./32/rln-v1.md) protocol.
This can be used in a couple of ways in applications:
1. Applications can add users to the [32/RLN-V1](./32/rln-v1.md) membership set in a batch.
2. Users of the application can register other users to the [32/RLN-V1](./32/rln-v1.md) membership set.
This is useful when the prospective user does not have access to funds on the network that [32/RLN-V1](./32/rln-v1.md) is deployed on.
## Wire Format Specification
The two parties, the requester and the receiver, MUST exchange the following information:
```protobuf
message Request {
// The spending public key of the requester
bytes spending_public_key = 1;
// The viewing public key of the requester
bytes viewing_public_key = 2;
}
```
### Generate Stealth Commitment
The application or user SHOULD generate a `stealth_commitment` after a request to do so is received.
This commitment MAY be inserted into the corresponding application membership set.
Once the membership set is updated, the receiver SHOULD exchange the following as a response to the request:
```protobuf
message Response {
// The used to check if the stealth_commitment belongs to the requester
bytes view_tag = 2;
// The stealth commitment for the requester
bytes stealth_commitment = 3;
// The ephemeral public key used to generate the commitment
bytes ephemeral_public_key = 4;
}
```
The receiver MUST generate an `ephemeral_public_key`, `view_tag` and `stealth_commitment`.
This will be used to check the stealth commitment used to register to the membership set,
and the user MUST be able to check ownership with their `viewing_public_key`.
## Implementation Suggestions
An implementation of the Stealth Address scheme is available in the [erc-5564-bn254](https://github.com/rymnc/erc-5564-bn254) repository,
which also includes a test to generate a stealth commitment for a given user.
## Security/Privacy Considerations
This specification inherits the security and privacy considerations of the [Stealth Address](https://eips.ethereum.org/EIPS/eip-5564) scheme.
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
- [10/Waku2](../waku/standards/core/10/waku2.md)
- [32/RLN-V1](./32/rln-v1.md)
- [ERC-5564](https://eips.ethereum.org/EIPS/eip-5564)

View File

@@ -1,6 +1,5 @@
---
slug: 58
title: 58/RLN-V2
title: RLN-V2
name: Rate Limit Nullifier V2
status: raw
editor: Rasul Ibragimov <curryrasul@gmail.com>

69
vac/raw/url-scheme.md Normal file
View File

@@ -0,0 +1,69 @@
---
title: STATUS-URL-SCHEME
name: Status URL Scheme
status: raw
category: Standards Track
tags:
editor: Felicio Mununga <felicio@status.im>
contributors:
---
## Abstract
This document describes URL scheme for previewing and deep linking content as well as for triggering actions.
## Background / Rationale / Motivation
### Requirements
#### Related scope
##### Features
- Onboarding website
- Link preview
- Link sharing
- Deep linking
- Routing and navigation
- Payment requests
- Chat creation
## Wire Format Specification / Syntax
### Schemes
- Internal `status-app://`
- External `https://` (i.e. univers/deep links)
### Paths
| Name | Url | Description |
| ----- | ---- | ---- |
| User profile | `/u/<encoded_data>#<user_chat_key>` | Preview/Open user profile |
| | `/u#<user_chat_key>` | |
| | `/u#<ens_name>` | |
| Community | `/c/<encoded_data>#<community_chat_key>` | Preview/Open community |
| | `/c#<community_chat_key>` | |
| Community channel | `/cc/<encoded_data>#<community_chat_key >`| Preview/Open community channel |
| | `/cc/<channel_uuid>#<community_chat_key>` | |
<!-- # Security/Privacy Considerations
A standard track RFC in `stable` status MUST feature this section.
A standard track RFC in `raw` or `draft` status SHOULD feature this section.
Informational RFCs (in any state) may feature this section.
If there are none, this section MUST explicitly state that fact.
This section MAY contain additional relevant information, e.g. an explanation as to why there are no security consideration for the respective document. -->
## Discussions
- See <https://github.com/status-im/specs/pull/159>
- See <https://github.com/status-im/status-web/issues/327>
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
- [STATUS-URL-DATA](./url-data.md)

View File

@@ -1,4 +1,4 @@
## Waku RFCs
# Waku RFCs
Waku builds a family of privacy-preserving, censorship-resistant communication protocols for web3 applications.

View File

@@ -2,7 +2,7 @@
slug: 16
title: 16/WAKU2-RPC
name: Waku v2 RPC API
status: draft
status: deprecated
tags: waku-core
editor: Hanno Cornelius <hanno@status.im>
---
@@ -176,7 +176,7 @@ The `get_waku_v2_relay_v1_messages` method returns a list of messages that were
## Relay Private API
The Private API provides functionality to encrypt/decrypt `WakuMessage` payloads using either symmetric or asymmetric cryptography. This allows backwards compatibility with [Waku v1 nodes](../6/waku1.md).
The Private API provides functionality to encrypt/decrypt `WakuMessage` payloads using either symmetric or asymmetric cryptography. This allows backwards compatibility with [Waku v1 nodes](../../legacy/6/waku1.md).
It is the API client's responsibility to keep track of the keys used for encrypted communication. Since keys must be cached by the client and provided to the node to encrypt/decrypt payloads, a Private API SHOULD NOT be exposed on non-local or untrusted nodes.
### Types

View File

@@ -2,7 +2,7 @@
slug: 18
title: 18/WAKU2-SWAP
name: Waku SWAP Accounting
status: draft
status: deprecated
editor: Oskar Thorén <oskarth@titanproxy.com>
contributor: Ebube Ud <ebube@status.im>
---
@@ -141,7 +141,7 @@ In the soft phase only accounting is performed, without consequence for the
peers. No disconnect or sending of cheques is performed at this tage.
SWAP protocol is performed in conjunction with another request-reply protocol to account for its usage.
It SHOULD be done for [13/WAKU2-STORE](../../standards/core/13/store.md)
It SHOULD be done for [13/WAKU2-STORE](../../core/13/store.md)
and it MAY be done for other request/reply protocols.
A client SHOULD log accounting state per peer
@@ -173,7 +173,7 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
1. [Prisoner's Dilemma](https://en.wikipedia.org/wiki/Prisoner%27s_dilemma)
2. [Axelrod - Evolution of Cooperation (book)](https://en.wikipedia.org/wiki/The_Evolution_of_Cooperation)
3. [Book of Swarm](https://web.archive.org/web/20210126130038/https://gateway.ethswarm.org/bzz/latest.bookofswarm.eth)
4. [13/WAKU2-STORE](../../standards/core/13/store.md)
4. [13/WAKU2-STORE](../../core/13/store.md)
<!--

View File

@@ -1,4 +1,4 @@
## Deprecated RFCs
# Deprecated RFCs
Deprecated specifications are no longer used in Waku products.
This subdirectory is for achrive purpose and

View File

@@ -89,7 +89,7 @@ This is used for content based filtering.
See [14/WAKU2-MESSAGE spec](../../standards/core/14/message.md) for where this is specified.
Note that this doesn't impact routing of messages between relaying nodes,
but it does impact how request/reply protocols such as
[12/WAKU2-FILTER](../../standards/core/14/filter.md) and [13/WAKU2-STORE](../../standards/core/13/store.md) are used.
[12/WAKU2-FILTER](../../standards/core/12/filter.md) and [13/WAKU2-STORE](../../standards/core/13/store.md) are used.
This is especially useful for nodes that have limited bandwidth,
and only want to pull down messages that match this given content topic.
@@ -163,7 +163,7 @@ Copyright and related rights waived via
* [RELAY-SHARDING](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/relay-sharding.md)
* [Ethereum 2 P2P spec](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/p2p-interface.md#topics-and-messages)
* [14/WAKU2-MESSAGE](../../standards/core/14/message.md)
* [12/WAKU2-FILTER](../../standards/core/14/filter.md)
* [12/WAKU2-FILTER](../../standards/core/12/filter.md)
* [13/WAKU2-STORE](../../standards/core/13/store.md)
* [6/WAKU1](../../deprecated/5/waku0.md)
* [15/WAKU-BRIDGE](../../standards/core/15/bridge.md)

View File

@@ -74,7 +74,7 @@ This requires keeping track of the [last time each peer was disconnected](#track
A Waku v2 client MAY choose to implement a keep-alive mechanism to certain peers.
If a client chooses to implement keep-alive on a connection,
it SHOULD do so by sending periodic [libp2p pings](https://docs.libp2p.io/concepts/protocols/#ping) as per `10/WAKU2` [client recommendations](../../standards/core/10/WAKU2.md/#recommendations-for-clients).
it SHOULD do so by sending periodic [libp2p pings](https://docs.libp2p.io/concepts/protocols/#ping) as per `10/WAKU2` [client recommendations](../../standards/core/10/waku2.md/#recommendations-for-clients).
The recommended period between pings SHOULD be _at most_ 50% of the shortest idle connection timeout for the specific client and transport.
For example, idle TCP connections often times out after 10 to 15 minutes.
@@ -96,4 +96,4 @@ Copyright and related rights waived via
- [`18/WAKU2-SWAP`](../../standards/application/18/swap.md)
- [backing off period](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#prune-backoff-and-peer-exchange)
- [libp2p pings](https://docs.libp2p.io/concepts/protocols/#ping)
- [`10/WAKU2` client recommendations](https://rfc.vac.dev/spec/10/#recommendations-for-clients)
- [`10/WAKU2` client recommendations](../../standards/core/10/waku2.md/#recommendations-for-clients)

View File

@@ -46,10 +46,10 @@ The proposed protocol MUST adhere to the following design requirements:
2. Bob is willing to participate to Eth-PM, and publishes `B'`,
3. Bob's ownership of `B'` MUST be verifiable,
4. Alice wants to send message `M` to Bob,
5. Bob SHOULD be able to get `M` using [10/WAKU2 spec](../../standards/core/10/waku2.md),
5. Bob SHOULD be able to get `M` using [10/WAKU2 spec](../../core/10/waku2.md),
6. Participants only have access to their Ethereum Wallet via the Web3 API,
7. Carole MUST NOT be able to read `M`'s content even if she is storing it or relaying it,
8. [Waku Message Version 1](../../standards/application/26/payload.md) Asymmetric Encryption is used for encryption purposes.
8. [Waku Message Version 1](../26/payload.md) Asymmetric Encryption is used for encryption purposes.
## Limitations
@@ -155,7 +155,7 @@ it is not enough in itself to deduce Bob's Public Key.
This is why the protocol dictates that Bob MUST send his Public Key first,
and Alice MUST receive it before she can send him a message.
Moreover, nim-waku, the reference implementation of [13/WAKU2-STORE](../../standards/core/13/store.md)),
Moreover, nim-waku, the reference implementation of [13/WAKU2-STORE](../../core/13/store.md),
stores messages for a maximum period of 30 days.
This means that Bob would need to broadcast his public key at least every 30 days to be reachable.
@@ -202,10 +202,10 @@ Alice MAY monitor the Waku v2 to collect Ethereum Address and Encryption Public
Alice SHOULD verify that the `signature`s of `PublicKeyMessage`s she receives are valid as per EIP-712.
She SHOULD drop any message without a signature or with an invalid signature.
Using Bob's Encryption Public Key, retrieved via [10/WAKU2](../../standards/core/10/waku2.md), Alice MAY now send an encrypted message to Bob.
Using Bob's Encryption Public Key, retrieved via [10/WAKU2 spec](../../core/10/waku2.md), Alice MAY now send an encrypted message to Bob.
If she wishes to do so, Alice MUST encrypt her message `M` using Bob's Encryption Public Key `B'`,
as per [26/WAKU-PAYLOAD Asymmetric Encryption specs](../../standards/application/26/payload.md/#asymmetric).
as per [26/WAKU-PAYLOAD Asymmetric Encryption specs](../26/payload.md/#asymmetric).
Alice SHOULD now publish this message on the Private Message content topic.
@@ -214,12 +214,12 @@ Alice SHOULD now publish this message on the Private Message content topic.
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
- [10/WAKU2 spec](../../standards/core/10/waku2.md)
- [Waku Message Version 1](../../standards/application/26/payload.md)
- [10/WAKU2 spec](../../core/10/waku2.md)
- [Waku Message Version 1](../26/payload.md)
- [X3DH](https://www.signal.org/docs/specifications/x3dh/)
- [Double Ratchet](https://signal.org/docs/specifications/doubleratchet/)
- [Status secure transport spec](https://specs.status.im/spec/5)
- [EIP-712](https://eips.ethereum.org/EIPS/eip-712)
- [13/WAKU2-STORE](../../standards/core/13/store.md))
- [13/WAKU2-STORE](../../core/13/store.md)
- [The Graph](https://thegraph.com/)

View File

@@ -7,14 +7,14 @@ editor: Sanaz Taheri <sanaz@status.im>
contributors:
---
The reliability of [13/WAKU2-STORE](../../standards/core/13/store.md) protocol heavily relies on the fact that full nodes i.e., those who persist messages have high availability and uptime and do not miss any messages.
The reliability of [13/WAKU2-STORE](../../core/13/store.md) protocol heavily relies on the fact that full nodes i.e., those who persist messages have high availability and uptime and do not miss any messages.
If a node goes offline, then it will risk missing all the messages transmitted in the network during that time.
In this specification, we provide a method that makes the store protocol resilient in presence of faulty nodes.
Relying on this method, nodes that have been offline for a time window will be able to fix the gap in their message history when getting back online.
Moreover, nodes with lower availability and uptime can leverage this method to reliably provide the store protocol services as a full node.
## Method description
As the first step towards making the [13/WAKU2-STORE](../../standards/core/13/store.md) protocol fault-tolerant, we introduce a new type of time-based query through which nodes fetch message history from each other based on their desired time window.
As the first step towards making the [13/WAKU2-STORE](../../core/13/store.md) protocol fault-tolerant, we introduce a new type of time-based query through which nodes fetch message history from each other based on their desired time window.
This method operates based on the assumption that the querying node knows some other nodes in the store protocol which have been online for that targeted time window.
## Security Consideration
@@ -23,7 +23,7 @@ The main security consideration to take into account while using this method is
This will gradually result in the extraction of the node's activity pattern which can lead to inference attacks.
## Wire Specification
We extend the [HistoryQuery](../../standards/core/13/store.md/#payloads) protobuf message with two fields of `start_time` and `end_time` to signify the time range to be queried.
We extend the [HistoryQuery](../../core/13/store.md/#payloads) protobuf message with two fields of `start_time` and `end_time` to signify the time range to be queried.
### Payloads
@@ -46,10 +46,10 @@ message HistoryQuery {
RPC call to query historical messages.
- `start_time`: this field MAY be filled out to signify the starting point of the queried time window.
This field holds the Unix epoch time in nanoseconds.
The `messages` field of the corresponding [`HistoryResponse`](../../standards/core/13/store.md/#HistoryResponse) MUST contain historical waku messages whose [`timestamp`](../../standards/core/14/message.md/#Payloads) is larger than or equal to the `start_time`.
The `messages` field of the corresponding [`HistoryResponse`](../../core/13/store.md/#HistoryResponse) MUST contain historical waku messages whose [`timestamp`](../../core/14/message.md/#Payloads) is larger than or equal to the `start_time`.
- `end_time` this field MAY be filled out to signify the ending point of the queried time window.
This field holds the Unix epoch time in nanoseconds.
The `messages` field of the corresponding [`HistoryResponse`](../../standards/core/13/store.md/#HistoryResponse) MUST contain historical waku messages whose [`timestamp`](../../standards/core/14/message.md/#Payloads) is less than or equal to the `end_time`.
The `messages` field of the corresponding [`HistoryResponse`](../../core/13/store.md/#HistoryResponse) MUST contain historical waku messages whose [`timestamp`](../../core/14/message.md/#Payloads) is less than or equal to the `end_time`.
A time-based query is considered valid if its `end_time` is larger than or equal to the `start_time`.
Queries that do not adhere to this condition will not get through e.g. an open-end time query in which the `start_time` is given but no `end_time` is supplied is not valid.
@@ -61,7 +61,7 @@ In order to account for nodes asynchrony, and assuming that nodes may be out of
That is if the original window is [`l`,`r`] then the history query SHOULD be made for `[start_time: l - 20s, end_time: r + 20s]`.
Note that `HistoryQuery` preserves `AND` operation among the queried attributes.
As such, The `messages` field of the corresponding [`HistoryResponse`](../../standards/core/13/store.md/#HistoryResponse) MUST contain historical waku messages that satisfy the indicated `pubsubtopic` AND `contentFilters` AND the time range [`start_time`, `end_time`].
As such, The `messages` field of the corresponding [`HistoryResponse`](../../core/13/store.md/#HistoryResponse) MUST contain historical waku messages that satisfy the indicated `pubsubtopic` AND `contentFilters` AND the time range [`start_time`, `end_time`].
## Copyright
@@ -70,5 +70,5 @@ Copyright and related rights waived via
## References
- [13/WAKU2-STORE](../../standards/core/13/store.md)
- [13/WAKU2-STORE](../../core/13/store.md)
- [`timestamp`](../../standards/core/14/message.md/#Payloads)

View File

@@ -8,9 +8,9 @@ contributors:
---
This specification describes how Waku provides confidentiality, authenticity, and integrity, as well as some form of unlinkability.
Specifically, it describes how encryption, decryption and signing works in [6/WAKU1](../../standards/core/6/waku1.md) and in [10/WAKU2 spec](../../standards/core/10/waku2.md) with [14/WAKU-MESSAGE version 1](../../standards/core/14/message.md/#version1).
Specifically, it describes how encryption, decryption and signing works in [6/WAKU1](../../legacy/6/waku1.md) and in [10/WAKU2 spec](../../core/10/waku2.md) with [14/WAKU-MESSAGE version 1](../../core/14/message.md/#version1).
This specification effectively replaces [7/WAKU-DATA](../../standards/application/7/DATA.md) as well as [6/WAKU1 Payload encryption](../../standards/core/6/waku1.md/#payload-encryption) but written in a way that is agnostic and self-contained for Waku v1 and Waku v2.
This specification effectively replaces [7/WAKU-DATA](../../legacy/7/data.md) as well as [6/WAKU1 Payload encryption](../../legacy/6/waku1.md/#payload-encryption) but written in a way that is agnostic and self-contained for Waku v1 and Waku v2.
Large sections of the specification originate from [EIP-627: Whisper spec](https://eips.ethereum.org/EIPS/eip-627) as well from [RLPx Transport Protocol spec (ECIES encryption)](https://github.com/ethereum/devp2p/blob/master/rlpx.md#ecies-encryption) with some modifications.
@@ -42,9 +42,9 @@ ECIES is using the following cryptosystem:
## Specification
For 6/WAKU1, the `data` field is used in the `waku envelope`, and the field MAY contain the encrypted payload.
For [6/WAKU1](../../legacy/6/waku1.md), the `data` field is used in the `waku envelope`, and the field MAY contain the encrypted payload.
For 10/WAKU2, the `payload` field is used in `WakuMessage` and MAY contain the encrypted payload.
For [10/WAKU2 spec](../../core/10/waku2.md), the `payload` field is used in `WakuMessage` and MAY contain the encrypted payload.
The fields that are concatenated and encrypted as part of the `data` (Waku v1) / `payload` (Waku v2) field are:
- flags
@@ -142,10 +142,10 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
## References
1. [6/WAKU1](../../standards/core/6/waku1.md)
2. [10/WAKU2 spec](../../standards/core/10/waku2.md)
3. [14/WAKU-MESSAGE version 1](../../standards/core/14/message.md/#version1)
4. [7/WAKU-DATA](../../standards/application/7/DATA.md)
1. [6/WAKU1](../../legacy/6/waku1.md)
2. [10/WAKU2 spec](../../core/10/waku2.md)
3. [14/WAKU-MESSAGE version 1](../../core/14/message.md/#version1)
4. [7/WAKU-DATA](../../legacy/7/data.md)
5. [EIP-627: Whisper spec](https://eips.ethereum.org/EIPS/eip-627)
6. [RLPx Transport Protocol spec (ECIES encryption)](https://github.com/ethereum/devp2p/blob/master/rlpx.md#ecies-encryption)
7. [Status 5/SECURE-TRANSPORT](https://specs.status.im/spec/5)

View File

@@ -54,7 +54,7 @@ Types used in this specification are defined using the [Protobuf](https://develo
End-to-end encryption (E2EE) takes place between two clients.
The main cryptographic protocol is a Double Ratchet protocol, which is derived from the [Off-the-Record protocol](https://otr.cypherpunks.ca/Protocol-v3-4.1.1.html), using a different ratchet.
[The Waku v2 protocol](../../standards/core/10/waku2.md) subsequently encrypts the message payload, using symmetric key encryption.
[The Waku v2 protocol](../../core/10/waku2.md) subsequently encrypts the message payload, using symmetric key encryption.
Furthermore, the concept of prekeys (through the use of [X3DH](https://signal.org/docs/specifications/x3dh/)) is used 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.
@@ -230,7 +230,7 @@ The message key MUST be used to encrypt the next message to be sent.
1. Inherits the security considerations of [X3DH](https://signal.org/docs/specifications/x3dh/#security-considerations) and [Double Ratchet](https://signal.org/docs/specifications/doubleratchet/#security-considerations).
2. Inherits the security considerations of the [Waku v2 protocol](../../standards/core/10/waku2.md).
2. Inherits the security considerations of the [Waku v2 protocol](../../core/10/waku2.md).
3. The protocol is designed to be used in a decentralized manner, however, it is possible to use a centralized server to serve prekey bundles. In this case, the server is trusted.
@@ -249,7 +249,7 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
- [Signal's Double Ratchet](https://signal.org/docs/specifications/doubleratchet/)
- [Protobuf](https://developers.google.com/protocol-buffers/)
- [Off-the-Record protocol](https://otr.cypherpunks.ca/Protocol-v3-4.1.1.html)
- [The Waku v2 protocol](../../standards/core/10/waku2.md)
- [The Waku v2 protocol](../../core/10/waku2.md)
- [HKDF](https://www.rfc-editor.org/rfc/rfc5869)
- [2/ACCOUNT](https://specs.status.im/spec/2#x3dh-prekey-bundles)
- [reference wire format](https://github.com/status-im/status-go/blob/a904d9325e76f18f54d59efc099b63293d3dcad3/services/shhext/chat/encryption.proto#L12)

View File

@@ -19,7 +19,7 @@ contributors:
This document specifies how to manage sessions based on an X3DH key exchange.
This includes how to establish new sessions, how to re-establish them, how to maintain them, and how to close them.
[53/WAKU2-X3DH](../../standards/application/53/X3DH.md) specifies the Waku `X3DH` protocol for end-to-end encryption.
[53/WAKU2-X3DH](../53/x3dh.md) specifies the Waku `X3DH` protocol for end-to-end encryption.
Once two peers complete an X3DH handshake, they SHOULD establish an X3DH session.
## Session Establishment
@@ -146,7 +146,7 @@ In this case an empty message containing bundle information MUST be sent back, w
## Security Considerations
1. Inherits all security considerations from [53/WAKU2-X3DH](../../standards/application/53/X3DH.md).
1. Inherits all security considerations from [53/WAKU2-X3DH](../53/x3dh.md).
### Recommendations
@@ -159,6 +159,6 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
## References
1. [53/WAKU2-X3DH](../../standards/application/53/X3DH.md)
1. [53/WAKU2-X3DH](../53/x3dh.md)
2. [Signal's Sesame Algorithm](https://signal.org/docs/specifications/sesame/)

View File

@@ -3,12 +3,13 @@ slug: 10
title: 10/WAKU2
name: Waku v2
status: draft
editor: Oskar Thorén <oskarth@titanproxy.com>
editor: Hanno Cornelius <hanno@status.im>
contributors:
- Sanaz Taheri <sanaz@status.im>
- Hanno Cornelius <hanno@status.im>
- Reeshav Khan <reeshav@status.im>
- Daniel Kaiser <danielkaiser@status.im>
- Oskar Thorén <oskarth@titanproxy.com>
---
## Abstract
@@ -23,7 +24,7 @@ These capabilities are things such as:
This makes Waku ideal for running a p2p protocol on mobile and in similarly restricted environments.
Historically, it has its roots in [6/WAKU1](../6/waku1.md),
Historically, it has its roots in [6/WAKU1](../../legacy/6/waku1.md),
which stems from [Whisper](https://eips.ethereum.org/EIPS/eip-627), originally part of the Ethereum stack.
However, Waku v2 acts more as a thin wrapper for PubSub and has a different API.
It is implemented in an iterative manner where initial focus is on porting essential functionality to libp2p.
@@ -211,7 +212,7 @@ This is used to fetch historical messages for mostly offline devices.
See [13/WAKU2-STORE spec](../13/store.md) spec for more details.
There is also an experimental fault-tolerant addition to the store protocol that relaxes the high availability requirement.
See [21/WAKU2-FT-STORE](../../application/21/ft-store.md)
See [21/WAKU2-FT-STORE](../../application/21/fault-tolerant-store.md)
#### Content filtering
@@ -244,9 +245,9 @@ The PubSub topics `pubtopic1` and `pubtopic2` is used for routing and indicates
Ditto for [13/WAKU2-STORE](../13/store.md) where it indicates that these messages are persisted on that node.
1. Node A creates a WakuMessage `msg1` with a ContentTopic `contentTopic1`.
See [14/WAKU2-MESSAGE](../core/14/message.md) for more details.
If WakuMessage version is set to 1, we use the [6/WAKU1](../6/waku1.md) compatible `data` field with encryption.
See [7/WAKU-DATA](../../application/7/data.md) for more details.
See [14/WAKU2-MESSAGE](../14/message.md) for more details.
If WakuMessage version is set to 1, we use the [6/WAKU1](../../legacy/6/waku1.md) compatible `data` field with encryption.
See [7/WAKU-DATA](../../legacy/7/data.md) for more details.
2. Node F requests to get messages filtered by PubSub topic `pubtopic1` and ContentTopic `contentTopic1`.
Node D subscribes F to this filter and will in the future forward messages that match that filter.
@@ -362,10 +363,10 @@ This includes Waku v1 specs, as they are used for bridging between the two netwo
| Spec | nim-waku (Nim) | go-waku (Go) | js-waku (Node JS) | js-waku (Browser JS) |
| ---- | -------------- | ------------ | ----------------- | -------------------- |
|[6/WAKU1](../6/waku1.md)|✔|||
|[7/WAKU-DATA](../7/data.md)|✔|✔||
|[8/WAKU-MAIL](../../application/8/mail.md)|✔|||
|[9/WAKU-RPC](../9/waku2-rpc.md)|✔|||
|[6/WAKU1](../../legacy/6/waku1.md)|✔|||
|[7/WAKU-DATA](../../legacy/7/data.md)|✔|✔||
|[8/WAKU-MAIL](../../legacy/8/mail.md)|✔|||
|[9/WAKU-RPC](../../legacy/9/rpc.md)|✔|||
|[10/WAKU2](../10/waku2.md)|✔|🚧|🚧|🚧|
|[11/WAKU2-RELAY](../11/relay.md)|✔|✔|✔|✔|
|[12/WAKU2-FILTER](../12/filter.md)|✔|✔||
@@ -393,7 +394,7 @@ To implement a minimal Waku v2 client, we recommend implementing the following s
To get compatibility with Waku v1:
- [7/WAKU-DATA](../7/data.md)
- [7/WAKU-DATA](../../legacy/7/data.md)
- [14/WAKU2-MESSAGE](../14/message.md) - version 1 (encrypted with `7/WAKU-DATA`)
For an interoperable keep-alive mechanism:
@@ -429,7 +430,7 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
1. [libp2p specs](https://github.com/libp2p/specs)
2. [6/WAKU1](../6/waku1.md)
2. [6/WAKU1](../../legacy/6/waku1.md)
3. [Whisper spec (EIP627)](https://eips.ethereum.org/EIPS/eip-627)
@@ -473,7 +474,7 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
23. [19/WAKU2-LIGHTPUSH](../19/lightpush.md)
24. [7/WAKU-DATA](../../application/7/data.md)
24. [7/WAKU-DATA](../../legacy/7/data.md)
25. [15/WAKU-BRIDGE](../15/bridge.md)
@@ -487,9 +488,9 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
30. [js-waku (NodeJS and Browser)](https://github.com/status-im/js-waku/)
31. [8/WAKU-MAIL](../../application/8/mail.md)
31. [8/WAKU-MAIL](../../legacy/8/mail.md)
32. [9/WAKU-RPC](../9/waku2-rpc.md)
32. [9/WAKU-RPC](../../legacy/9/rpc.md)
33. [16/WAKU2-RPC](../16/rpc.md)

View File

@@ -4,11 +4,13 @@ title: 13/WAKU2-STORE
name: Waku v2 Store
status: draft
tags: waku-core
editor: Sanaz Taheri <sanaz@status.im>
editor: Simon-Pierre Vivier <simvivier@status.im>
contributors:
- Dean Eigenmann <dean@status.im>
- Oskar Thorén <oskarth@titanproxy.com>
- Aaryamann Challani <aaryamann@status.im>
- Sanaz Taheri <sanaz@status.im>
- Hanno Cornelius <hanno@status.im>
---
## Abstract

View File

@@ -11,81 +11,68 @@ contributors:
- Aaryamann Challani <aaryamann@status.im>
- Lorenzo Delgado <lorenzo@status.im>
- Abhimanyu Rawat <abhi@status.im>
- Oskar Thorén <oskar@status.im>
- Oskar Thorén <oskarth@titanproxy.com>
---
## Abstract
[10/WAKU2](/spec/10) is a family of modular peer-to-peer protocols for secure communication.
These protocols are designed to be secure, privacy-preserving,
censorship-resistant and run in resource-restricted environments.
At a high level, it implements a publish/subscribe, PubSub,
messaging mechanism over [libp2p](https://github.com/libp2p/specs) and adds capabilities.
Waku v2 is a family of modular peer-to-peer protocols for secure communication.
These protocols are designed to be secure, privacy-preserving, and censorship-resistant and can run in resource-restricted environments.
At a high level, Waku v2 implements a Pub/Sub messaging pattern over libp2p and adds capabilities.
The present document specifies the Waku v2 message format, a way to encapsulate the messages sent with specific information security goals, and Whisper/Waku v1 backward compatibility.
This specification describes the [10/WAKU2](/spec/10) messaging format.
A way to encapsulate the messages sent with specific information security goals, and
[6/WAKU1](/spec/6/) backward compatibility.
## Motivation
When sending messages over [10/WAKU2](/spec/10), there are multiple requirements:
When sending messages over Waku, there are multiple requirements:
- One may have a separate encryption layer as part of the application.
- One may want to provide efficient routing for resource-restricted devices.
- One may want to provide compatibility with [Waku v1 envelopes](/spec/6/).
- One may want to provide compatibility with [Waku v1 envelopes](../../legacy/6/waku1.md).
- One may want encrypted payloads by default.
- One may want to provide unlinkability to get metadata protection.
This specification attempts to provide for these various requirements.
## Semantics
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”,
and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).
### Waku Message
A `WakuMessage` is constituted by the combination of the data payload and attributes that, for example,
a *publisher* sends to a `pubsubTopic` and is eventually delivered to *subscribers*.
A Waku message is constituted by the combination of data payload and attributes that, for example, a *publisher* sends to a *topic* and is eventually delivered to *subscribers*.
The `WakuMessage` attributes are key-value pairs of metadata associated with a message.
The message data payload is part of the transmitted `WakuMessage` that is the actual message information.
The data payload is also treated as a `WakuMessage` attribute for convenience.
Waku message attributes are key-value pairs of metadata associated with a message.
And the message data payload is the part of the transmitted Waku message that is the actual message information.
The data payload is also treated as a Waku message attribute for convenience.
### Message Attributes
* The `payload` attribute MUST contain the message data payload to be sent.
* The `contentTopic` attribute MUST specify a string identifier that can be used for content-based filtering,
as desribed in [23/WAKU2-TOPICS](/spec/23/).
* The `content_topic` attribute MUST specify a string identifier that can be used for content-based filtering,
as described in [23/WAKU2-TOPICS](../../../informational/23/topics.md).
* The `meta` attribute, if present,
SHOULD contain an arbitrary application-specific variable-length byte array with a maximum length limit of 64 bytes.
This attribute can be utilized to convey supplementary details to various Waku protocols, thereby
enabling customized processing based on its contents.
* The `meta` attribute, if present, contains an arbitrary application-specific variable-length byte array with a maximum length limit of 64 bytes.
This attribute can be utilized to convey supplementary details to various Waku protocols, thereby enabling customized processing based on its contents.
* The `version` attribute, if present,
SHOULD contain a version number to discriminate different types of `payload` encryption.
* The `version` attribute, if present, contains a version number to discriminate different types of payload encryption.
If omitted, the value SHOULD be interpreted as version 0.
* The `timestamp` attribute, if present,
SHOULD signify the time at which the message was generated by its sender.
* The `timestamp` attribute, if present, signifies the time at which the message was generated by its sender.
This attribute MAY contain the Unix epoch time in nanoseconds.
If the attribute is omitted, it SHOULD be interpreted as timestamp 0.
* The `ephemeral` attribute, if present,
signifies the transient nature of the message.
For example, an ephemeral message SHOULD not be persisted by any [10/WAKU2](/spec/10) nodes.
If this attribute is set to `true`,
the message SHOULD be interpreted as ephemeral.
If the attribute is omitted or set to `false`,
the message SHOULD be interpreted as non-ephemeral.
* The `ephemeral` attribute, if present, signifies the transient nature of the message.
For example, an ephemeral message SHOULD not be persisted by the Waku network.
If this attribute is set to `true`, the message SHOULD be interpreted as ephemeral.
If, instead, the attribute is omitted or set to `false`, the message SHOULD be interpreted as non-ephemeral.
### Wire Format
## Wire Format
The `WakuMessage` wire format is specified using [protocol buffers v3](https://developers.google.com/protocol-buffers/).
The Waku message wire format is specified using [protocol buffers v3](https://developers.google.com/protocol-buffers/).
```protobuf
syntax = "proto3";
message WakuMessage {
@@ -96,143 +83,126 @@ message WakuMessage {
optional bytes meta = 11;
optional bool ephemeral = 31;
}
```
### Payload Encryption
An example proto file following this specification can be found [here (vacp2p/waku)](https://github.com/vacp2p/waku/blob/main/waku/message/v1/message.proto).
The `WakuMessage` payload MAY be encrypted.
## Payload encryption
The Waku message payload MAY be encrypted.
The message `version` attribute indicates the schema used to encrypt the payload data.
- **Version 0:**
The `payload` SHOULD be interpreted as unencrypted; additionally,
it MAY indicate that the message payload has been encrypted at the application layer.
The payload SHOULD be interpreted as unencrypted; additionally, it CAN indicate that the message payload has been encrypted at the application layer.
- **Version 1:**
The `payload` SHOULD be encrypted using [6/WAKU1](/spec/6/) payload encryption,
as specified in [26/WAKU-PAYLOAD](/spec/26).
The payload SHOULD be encrypted using Waku v1 payload encryption specified in [26/WAKU-PAYLOAD](../../application/26/payload.md).
This provides asymmetric and symmetric encryption.
The key agreement is performed out of band.
And provides an encrypted signature and padding for some form of unlinkability.
- **Version 2:**
The `payload` SHOULD be encoded according to the [35/WAKU2-NOISE](/spec/35) protocol,
which provides symmetric encryption and asymmetric key exchange.
The payload SHOULD be encoded according to [35/WAKU2-NOISE]([/spec/35](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise.md)).
Waku Noise protocol provides symmetric encryption and asymmetric key exchange.
Any `version` value not included in this list is reserved for a future specification.
And, in this case, the `payload` SHOULD be interpreted as unencrypted by the Waku layer.
Any `version` value not included in this list is reserved for future specification.
And, in this case, the payload SHOULD be interpreted as unencrypted by the Waku layer.
### Whisper/Waku v1 Envelope Compatibility
Whisper/[6/WAKU1](/spec/6/) envelopes are compatible with [10/WAKU2](/spec/10) messages format.
## Whisper/Waku v1 envelope compatibility
* Whisper/[6/WAKU1](/spec/6/) `topic` field SHOULD be mapped to [10/WAKU2](/spec/10) message's `content_topic` attribute.
* Whisper/[6/WAKU1](/spec/6/) `data` field SHOULD be mapped to [10/WAKU2](/spec/10) message's `payload` attribute.
Whisper/Waku v1 envelopes are compatible with Waku v2 messages format.
[10/WAKU2](/spec/10) implements a pub/sub messaging pattern over libp2p.
This makes redundant some Whisper/[6/WAKU1](/spec/6/) envelope fields (e.g., `expiry`, `ttl`, `topic`, etc.), so
they can be ignored.
* Whisper/Waku v1 `topic` field SHOULD be mapped to Waku v2 message's `content_topic` attribute.
* Whisper/Waku v1 `data` field SHOULD be mapped to Waku v2 message's `payload` attribute.
### Deterministic Message Hashing
Waku v2 implements a pub/sub messaging pattern over libp2p.
This makes redundant some Whisper/Waku v1 envelope fields (e.g., `expiry`, `ttl`, `topic`, etc.), so they can be ignored.
In Protocol Buffers v3,
the deterministic serialization is not canonical across the different implementations and languages.
## Deterministic message hashing
In Protocol Buffers v3, the deterministic serialization is not canonical across the different implementations and languages.
It is also unstable across different builds with schema changes due to unknown fields.
To overcome this interoperability limitation,
a `WakuMessage` hash MUST be computed following this schema:
To overcome this interoperability limitation, a Waku v2 message's hash MUST be computed following this schema:
```
messageHash = sha256(concat(pubsub_topic, WakuMessage.payload, WakuMessage.content_topic, WakuMessage.meta, WakuMessage.timestamp));
message_hash = sha256(concat(pubsub_topic, message.payload, message.content_topic, message.meta, message.timestamp))
```
If an optional attribute, such as `meta`, is absent,
the concatenation of attributes SHOULD exclude it.
This is RECOMMENDED to ensure that the concatenation process proceeds smoothly when certain attributes are missing and
to maintain backward compatibility.
If an optional attribute, such as `meta`, is absent, the concatenation of attributes SHOULD exclude it. This recommendation is made to ensure that the concatenation process proceeds smoothly when certain attributes are missing and to maintain backward compatibility.
This hashing schema is deemed appropriate for use cases where a cross-implementation deterministic hash is needed,
such as message deduplication and integrity validation.
The collision probability offered by this hashing schema can be considered negligible.
This is due to the deterministic concatenation order of the message attributes,
coupled with using a SHA-2 (256-bit) hashing algorithm.
This hashing schema is deemed appropriate for use cases where a cross-implementation deterministic hash is needed, such as message deduplication and integrity validation. The collision probability offered by this hashing schema can be considered negligible. This is due to the deterministic concatenation order of the message attributes, coupled with using a SHA-2 (256-bit) hashing algorithm.
### Test Vectors
### Test vectors
`WakuMessage` hash computation (`meta` size of 12 bytes):
Waku message hash computation (`meta` size of 12 bytes):
```
pubsub_topic = "/waku/2/default-waku/proto" (0x2f77616b752f322f64656661756c742d77616b752f70726f746f)
WakuMessage.payload = 0x010203045445535405060708
WakuMessage.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
WakuMessage.meta = 0x73757065722d736563726574
WakuMessage.timestamp = 0x175789bfa23f8400
message.payload = 0x010203045445535405060708
message.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
message.meta = 0x73757065722d736563726574
message.timestamp = 0x175789bfa23f8400
messageHash = 0x64cce733fed134e83da02b02c6f689814872b1a0ac97ea56b76095c3c72bfe05
message_hash = 0x64cce733fed134e83da02b02c6f689814872b1a0ac97ea56b76095c3c72bfe05
```
`WakuMessage` hash computation (`meta` size of 64 bytes):
Waku message hash computation (`meta` size of 64 bytes):
```
pubsub_topic = "/waku/2/default-waku/proto" (0x2f77616b752f322f64656661756c742d77616b752f70726f746f)
WakuMessage.payload = 0x010203045445535405060708
WakuMessage.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
WakuMessage.meta = 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
WakuMessage.timestamp = 0x175789bfa23f8400
message.payload = 0x010203045445535405060708
message.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
message.meta = 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
message.timestamp = 0x175789bfa23f8400
messageHash = 0x7158b6498753313368b9af8f6e0a0a05104f68f972981da42a43bc53fb0c1b27
message_hash = 0x7158b6498753313368b9af8f6e0a0a05104f68f972981da42a43bc53fb0c1b27
```
`WakuMessage` hash computation (`meta` attribute not present):
Waku message hash computation (`meta` attribute not present):
```
pubsub_topic = "/waku/2/default-waku/proto" (0x2f77616b752f322f64656661756c742d77616b752f70726f746f)
WakuMessage.payload = 0x010203045445535405060708
WakuMessage.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
WakuMessage.meta = <not-present>
WakuMessage.timestamp = 0x175789bfa23f8400
message.payload = 0x010203045445535405060708
message.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
message.meta = <not-present>
message.timestamp = 0x175789bfa23f8400
messageHash = 0xa2554498b31f5bcdfcbf7fa58ad1c2d45f0254f3f8110a85588ec3cf10720fd8
message_hash = 0xa2554498b31f5bcdfcbf7fa58ad1c2d45f0254f3f8110a85588ec3cf10720fd8
```
`WakuMessage` hash computation (`payload` length 0):
Waku message hash computation (`payload` length 0):
```
pubsub_topic = "/waku/2/default-waku/proto" (0x2f77616b752f322f64656661756c742d77616b752f70726f746f)
WakuMessage.payload = []
WakuMessage.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
WakuMessage.meta = 0x73757065722d736563726574
WakuMessage.timestamp = 0x175789bfa23f8400
message.payload = []
message.content_topic = "/waku/2/default-content/proto" (0x2f77616b752f322f64656661756c742d636f6e74656e742f70726f746f)
message.meta = 0x73757065722d736563726574
message.timestamp = 0x175789bfa23f8400
messageHash = 0x483ea950cb63f9b9d6926b262bb36194d3f40a0463ce8446228350bd44e96de4
message_hash = 0x483ea950cb63f9b9d6926b262bb36194d3f40a0463ce8446228350bd44e96de4
```
## Security Considerations
### Confidentiality, Integrity, and Authenticity
### Confidentiality, integrity, and authenticity
The level of confidentiality, integrity, and
authenticity of the `WakuMessage` data payload is discretionary.
Accordingly, the application layer shall utilize the encryption and
signature schemes supported by [10/WAKU2](/spec/10) to meet the application-specific privacy needs.
The level of confidentiality, integrity, and authenticity of the Waku message payload is discretionary.
Accordingly, the application layer shall utilize the encryption and signature schemes supported by Waku v2 to meet the application-specific privacy needs.
### Reliability of the `timestamp` attribute
The `timestamp` attribute is set by the sender.
Therefore, because message timestamps arent independently verified,
this attribute is prone to exploitation and misuse.
The Waku message `timestamp` attribute is set by the sender.
Therefore, because message timestamps arent independently verified, this attribute is prone to exploitation and misuse.
It should not solely be relied upon for operations such as message ordering.
For example, a malicious actor can arbitrarily set the `timestamp` of a `WakuMessage` to a high value, so
that it always shows up as the most recent message in a chat application.
Applications using the `timestamp` attribute are RECOMMENDED
to use additional methods for more robust message ordering.
An example of how to deal with message ordering against adversarial message timestamps can be found in the Status protocol,
see [62/STATUS-PAYLOADS](/spec/62).
For example, a malicious actor can arbitrarily set the `timestamp` of a Waku message to a high value so that it always shows up as the most recent message in a chat application.
Applications using Waku messages `timestamp` attribute are recommended to use additional methods for more robust message ordering.
An example of how to deal with message ordering against adversarial message timestamps can be found in the Status protocol, see [62/STATUS-PAYLOADS](../../../../status/62/payloads.md/#clock-vs-timestamp-and-message-ordering).
### Reliability of the `ephemeral` attribute
The `ephemeral` attribute is set by the sender.
Since there is currently no incentive mechanism for network participants to behave correctly,
this attribute is inherently insecure.
A malicious actor can tamper with the value of the `ephemeral` attribute, and
the receiver would not be able to verify the integrity of the message.
The Waku message `ephemeral` attribute is set by the sender.
Since there is currently no incentive mechanism for network participants to behave correctly, this attribute is inherently insecure.
A malicious actor can tamper with the value of a Waku messages `ephemeral` attribute, and the receiver would not be able to verify the integrity of the message.
## Copyright
@@ -241,12 +211,8 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
## References
- [10/WAKU2](/spec/10)
- [6/WAKU1](/spec/6/)
- [23/WAKU2-TOPICS](/spec/23/)
- [64/WAKU2-NETWORK](/spec/64)
- [6/WAKU1](../../legacy/6/waku1.md)
- [Google Protocol buffers v3](https://developers.google.com/protocol-buffers/)
- [11/WAKU2-RELAY](/spec/11/)
- [26/WAKU-PAYLOAD](/spec/26)
- [35/WAKU2-NOISE](/spec/35)
- [62/STATUS-PAYLOADS](/spec/62)
- [26/WAKU-PAYLOAD](../../application/26/payload.md)
- [35/WAKU2-NOISE]([/spec/35](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/noise.md))
- [62/STATUS-PAYLOADS](../../../../status/62/payloads.md/#clock-vs-timestamp-and-message-ordering)

View File

@@ -4,119 +4,156 @@ title: 17/WAKU2-RLN-RELAY
name: Waku v2 RLN Relay
status: draft
tags: waku-core
editor: Sanaz Taheri <sanaz@status.im>
editor: Alvaro Revuelta <alvaro@status.im>
contributors:
- Oskar Thorén <oskarth@titanproxy.com>
- Aaryamann Challani <aaryamann@status.im>
- Sanaz Taheri <sanaz@status.im>
- Hanno Cornelius <hanno@status.im>
---
The `17/WAKU2-RLN-RELAY` protocol is an extension of `11/WAKU2-RELAY` which additionally provides spam protection using [Rate Limiting Nullifiers (RLN)](../../../../vac/32/rln-v1.md).
## Abstract
This specification describes the `17/WAKU2-RLN-RELAY` protocol,
which is an extension of [`11/WAKU2-RELAY`](../11/relay.md) to provide spam protection using [Rate Limiting Nullifiers (RLN)](../../../../vac/32/rln-v1.md).
The security objective is to contain spam activity in a GossipSub network by enforcing a global messaging rate to all the peers.
Peers that violate the messaging rate are considered spammers and their message is considered spam.
The security objective is to contain spam activity in the (64/WAKU-NETWORK)[] by enforcing a global messaging rate to all the peers.
Peers that violate the messaging rate are considered spammers and
their message is considered spam.
Spammers are also financially punished and removed from the system.
## Motivation
<!-- **Protocol identifier***: `/vac/waku/waku-rln-relay/2.0.0-alpha1` -->
In open and anonymous p2p messaging networks,
one big problem is spam resistance.
Existing solutions, such as Whispers proof of work,
are computationally expensive hence not suitable for resource-limited nodes.
Other reputation-based approaches might not be desirable,
due to issues around arbitrary exclusion and privacy.
# Motivation
We augment the [`11/WAKU2-RELAY`](../11/relay.md) protocol with a novel construct of [RLN](../../../../vac/32/rln-v1.md) to enable an efficient economic spam prevention mechanism that can be run in resource-constrained environments.
In open and anonymous p2p messaging networks, one big problem is spam resistance.
Existing solutions, such as Whispers proof of work are computationally expensive hence not suitable for resource-limited nodes.
Other reputation-based approaches might not be desirable, due to issues around arbitrary exclusion and privacy.
## Specification
We augment the [`11/WAKU2-RELAY`](/spec/11) protocol with a novel construct of [RLN](/spec/32) to enable an efficient economic spam prevention mechanism that can be run in resource-constrained environments.
# Flow
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [2119](https://www.ietf.org/rfc/rfc2119.txt).
### Flow
The messaging rate is defined by the `period` which indicates how many messages can be sent in a given period.
We define an `epoch` as $\lceil$ `unix_time` / `period` $\rceil$. For example, if `unix_time` is `1644810116` and we set `period` to `30`, then `epoch` is $\lceil$`(unix_time/period)`$\rceil$ `= 54827003`.
Note that `epoch` refers to epoch in RLN and not Unix epoch. This means a message can only be sent every period, where period is up to the application.
See see section [Recommended System Parameters](#recommended-system-parameters) for some recommended ways to set a sensible `period` value depending on the application.
We define an `epoch` as $\lceil$ `unix_time` / `period` $\rceil$.
For example, if `unix_time` is `1644810116` and we set `period` to `30`,
then `epoch` is $\lceil$ `(unix_time/period)` $\rceil$ `= 54827003`.
> **NOTE:** The `epoch` refers to the epoch in RLN and not Unix epoch.
This means a message can only be sent every period, where the `period` is up to the application.
See section [Recommended System Parameters](#recommended-system-parameters) for the RECOMMENDED method to set a sensible `period` value depending on the application.
Peers subscribed to a spam-protected `pubsubTopic` are only allowed to send one message per `epoch`.
The higher-level layers adopting `17/WAKU2-RLN-RELAY` MAY choose to enforce the messaging rate for `WakuMessages` with a specific `contentTopic` published on a `pubsubTopic`.
The higher-level layers adopting `17/WAKU2-RLN-RELAY` MAY choose to enforce the messaging rate for `WakuMessages` with a specific `contentTopic` published on a `pubsubTopic`.
#### Setup and Registration
A `pubsubTopic` that is spam-protected requires subscribed peers to form a [RLN group](../../../../vac/32/rln-v1.md).
- Peers MUST be registered to the RLN group to be able to publish messages.
- Registration MAY be moderated through a smart contract deployed on the Ethereum blockchain.
## Setup and Registration
Peers subscribed to a specific `pubsubTopic` form a [RLN group](/spec/32).
<!-- link to the RLN group definition in the RLN RFC -->
Peers MUST be registered to the RLN group to be able to publish messages.
Registration is moderated through a smart contract deployed on the Ethereum blockchain.
Each peer has an [RLN key pair](/spec/32) denoted by `sk` and `pk`.
The secret key `sk` is secret data and MUST be persisted securely by the peer.
The state of the membership contract contains the list of registered members' public identity keys i.e., `pk`s.
For the registration, a peer creates a transaction that invokes the registration function of the contract via which registers its `pk` in the group.
The transaction also transfers some amount of ether to the contract to be staked.
Each peer has an [RLN key pair](../../../../vac/32/rln-v1.md) denoted by `sk` and `pk`.
- The secret key `sk` is secret data and MUST be persisted securely by the peer.
- The state of the membership contract SHOULD contain a list of all registered members' public identity keys i.e.,
`pk`s.
For registration, a peer MUST create a transaction to invoke the registration function on the contract,
which registers its `pk` in the RLN group.
- The transaction MUST transfer additional tokens to the contract to be staked.
This amount is denoted by `staked_fund` and is a system parameter.
The peer who has the secret key `sk` associated with a registered `pk` would be able to withdraw a portion `reward_portion` of the staked fund by providing valid proof. <!-- a secure way to prove the possession of a pk is yet under discussion, maybe via commit and reveal -->
The peer who has the secret key `sk` associated with a registered `pk` would be able to withdraw a portion `reward_portion` of the staked fund by providing valid proof.
`reward_portion` is also a system parameter.
Note that `sk` is initially only known to its owning peer however, it may get exposed to other peers in case the owner attempts spamming the system i.e., sending more than one message per `epoch`.
> **NOTE:** Initially `sk` is only known to its owning peer however,
it may get exposed to other peers in case the owner attempts spamming the system i.e.,
sending more than one message per `epoch`.
An overview of registration is illustrated in Figure 1.
![Figure 1: Registration.](./images/rln-relay.png)
#### Publishing
## Publishing
To publish at a given `epoch`, the publishing peer proceeds based on the regular [`11/WAKU2-RELAY`](/spec/11) protocol.
However, to protect against spamming, each `WakuMessage` (which is wrapped inside the `data` field of a PubSub message) MUST carry a [`RateLimitProof`](##RateLimitProof) with the following fields.
To publish at a given `epoch`,
the publishing peer proceeds based on the regular [`11/WAKU2-RELAY`](../11/relay.md) protocol.
However, to protect against spamming, each `WakuMessage`
(which is wrapped inside the `data` field of a PubSub message)
MUST carry a [`RateLimitProof`](##RateLimitProof) with the following fields.
Section [Payload](#payloads) covers the details about the type and encoding of these fields.
The `merkle_root` contains the root of the Merkle tree.
- The `merkle_root` contains the root of the Merkle tree.
- The `epoch` represents the current epoch.
- The `nullifier` is an internal nullifier acting as a fingerprint that allows specifying whether two messages are published by the same peer during the same `epoch`.
- The `nullifier` is a deterministic value derived from `sk` and
`epoch` therefore any two messages issued by the same peer
(i.e., using the same `sk`) for the same `epoch` are guaranteed to have identical `nullifier`s.
- The `share_x` and `share_y` can be seen as partial disclosure of peer's `sk` for the intended `epoch`.
They are derived deterministically from peer's `sk` and
current `epoch` using [Shamir secret sharing scheme](../../../../vac/32/rln-v1.md).
The `epoch` represents the current epoch.
If a peer discloses more than one such pair (`share_x`, `share_y`) for the same `epoch`,
it would allow full disclosure of its `sk` and
hence get access to its staked fund in the membership contract.
The `nullifier` is an internal nullifier acting as a fingerprint that allows specifying whether two messages are published by the same peer during the same `epoch`.
The `nullifier` is a deterministic value derived from `sk` and `epoch` therefore any two messages issued by the same peer (i.e., using the same `sk`) for the same `epoch` are guaranteed to have identical `nullifier`s.
- The `proof` field is a zero-knowledge proof signifying that:
The `share_x` and `share_y` can be seen as partial disclosure of peer's `sk` for the intended `epoch`.
They are derived deterministically from peer's `sk` and current `epoch` using [Shamir secret sharing scheme](/spec/32).
If a peer discloses more than one such pair (`share_x`, `share_y`) for the same `epoch`, it would allow full disclosure of its `sk` and hence get access to its staked fund in the membership contract.
The `proof` field is a zero-knowledge proof signifying that:
1. The message owner is the current member of the group i.e., her/his identity commitment key `pk` is part of the membership group Merkle tree with the root `merkle_root`.
2. `share_x` and `share_y` are correctly computed.
1. The message owner is the current member of the group i.e.,
the peer's identity commitment key, `pk`,
is part of the membership group Merkle tree with the root `merkle_root`.
2. `share_x` and `share_y` are correctly computed.
3. The `nullifier` is constructed correctly.
For more details about the proof generation check [RLN](/spec/32)
For more details about the proof generation check [RLN](../../../../vac/32/rln-v1.md)
The proof generation relies on the knowledge of two pieces of private information i.e., `sk` and `authPath`.
The `authPath` is a subset of Merkle tree nodes by which a peer can prove the inclusion of its `pk` in the group. <!-- TODO refer to RLN RFC for authPath def -->
The proof generation also requires a set of public inputs which are: the Merkle tree root `merkle_root`, the current `epoch`, and the message for which the proof is going to be generated.
In `17/WAKU2-RLN-RELAY`, the message is the concatenation of `WakuMessage`'s `payload` filed and its `contentTopic` i.e., `payload||contentTopic`.
The proof generation also requires a set of public inputs which are:
the Merkle tree root `merkle_root`, the current `epoch`, and
the message for which the proof is going to be generated.
In `17/WAKU2-RLN-RELAY`, the message is the concatenation of `WakuMessage`'s `payload` filed and
its `contentTopic` i.e., `payload||contentTopic`.
## Group Synchronization
#### Group Synchronization
Proof generation relies on the knowledge of Merkle tree root `merkle_root` and `authPath` which both require access to the membership Merkle tree.
Getting access to the Merkle tree can be done in various ways.
One way is that all the peers construct the tree locally.
This can be done by listening to the registration and deletion events emitted by the membership contract.
Getting access to the Merkle tree can be done in various ways:
1. Peers construct the tree locally.
This can be done by listening to the registration and
deletion events emitted by the membership contract.
Peers MUST update the local Merkle tree on a per-block basis.
This is discussed further in the [Merkle Root Validation](#merkle-root-validation) section.
Another approach for synchronizing the state of slashed `pk`s is to disseminate such information through a p2p GossipSub network to which all peers are subscribed.
This is in addition to sending the deletion transaction to the membership contract.
2. For synchronizing the state of slashed `pk`s,
disseminate such information through a `pubsubTopic` to which all peers are subscribed.
A deletion transaction SHOULD occur on the membership contract.
The benefit of an off-chain slashing is that it allows real-time removal of spammers as opposed to on-chain slashing in which peers get informed with a delay,
where the delay is due to mining the slashing transaction.
For the group synchronization, one important security consideration is that peers MUST make sure they always use the most recent Merkle tree root in their proof generation.
For the group synchronization,
one important security consideration is that peers MUST make sure they always use the most recent Merkle tree root in their proof generation.
The reason is that using an old root can allow inference about the index of the user's `pk` in the membership tree hence compromising user privacy and breaking message unlinkability.
## Routing
#### Routing
Upon the receipt of a PubSub message via [`11/WAKU2-RELAY`](/spec/11) protocol, the routing peer parses the `data` field as a `WakuMessage` and gets access to the `RateLimitProof` field.
Upon the receipt of a PubSub message via [`11/WAKU2-RELAY`](../11/relay.md) protocol,
the routing peer parses the `data` field as a `WakuMessage` and gets access to the `RateLimitProof` field.
The peer then validates the `RateLimitProof` as explained next.
### Epoch Validation
If the `epoch` attached to the message is more than `max_epoch_gap` apart from the routing peer's current `epoch` then the message is discarded and considered invalid.
##### Epoch Validation
If the `epoch` attached to the `WakuMessage` is more than `max_epoch_gap`,
apart from the routing peer's current `epoch`,
then the `WakuMessage` MUST be discarded and considered invalid.
This is to prevent a newly registered peer from spamming the system by messaging for all the past epochs.
`max_epoch_gap` is a system parameter for which we provide some recommendations in section [Recommended System Parameters](#recommended-system-parameters).
### Merkle Root Validation
##### Merkle Root Validation
The routing peers MUST check whether the provided Merkle root in the `RateLimitProof` is valid.
It can do so by maintaining a local set of valid Merkle roots, which consist of `acceptable_root_window_size` past roots.
It can do so by maintaining a local set of valid Merkle roots,
which consist of `acceptable_root_window_size` past roots.
These roots refer to the final state of the Merkle tree after a whole block consisting of group changes is processed.
The Merkle roots are updated on a per-block basis instead of a per-event basis.
This is done because if Merkle roots are updated on a per-event basis, some peers could send messages with a root that refers to a Merkle tree state that might get invalidated while the message is still propagating in the network, due to many registrations happening during this time frame.
@@ -128,33 +165,38 @@ This also allows peers which are not well connected to the network to be able to
This network delay is related to the nature of asynchronous network conditions, which means that peers see membership changes asynchronously, and therefore may have differing local Merkle trees.
See [Recommended System Parameters](#recommended-system-parameters) on choosing an appropriate `acceptable_root_window_size`.
### Proof Verification
##### Proof Verification
The routing peers MUST check whether the zero-knowledge proof `proof` is valid.
It does so by running the zk verification algorithm as explained in [RLN](/spec/32).
If `proof` is invalid then the message is discarded.
It does so by running the zk verification algorithm as explained in [RLN](../../../../vac/32/rln-v1.md).
If `proof` is invalid then the message MUST be discarded.
### Spam detection
To enable local spam detection and slashing, routing peers MUST record the `nullifier`, `share_x`, and `share_y` of incoming messages which are not discarded i.e., not found spam or with invalid proof or epoch.
##### Spam detection
To enable local spam detection and slashing,
routing peers MUST record the `nullifier`, `share_x`, and `share_y`
of incoming messages which are not discarded i.e., not found spam or with invalid proof or epoch.
To spot spam messages, the peer checks whether a message with an identical `nullifier` has already been relayed.
1. If such a message exists and its `share_x` and `share_y` components are different from the incoming message, then slashing takes place.
That is, the peer uses the `share_x` and `share_y` of the new message and the `share'_x` and `share'_y` of the old record to reconstruct the `sk` of the message owner.
The `sk` then can be used to delete the spammer from the group and withdraw a portion `reward_portion` of its staked fund.
2. If the `share_x` and `share_y` fields of the previously relayed message are identical to the incoming message, then the message is a duplicate and shall be discarded.
3. If none is found, then the message gets relayed.
1. If such a message exists and its `share_x` and `share_y`
components are different from the incoming message, then slashing takes place.
That is, the peer uses the `share_x` and `share_y`
of the new message and the `share'_x` and `share'_y`
of the old record to reconstruct the `sk` of the message owner.
The `sk` then MAY be used to delete the spammer from the group and
withdraw a portion `reward_portion` of its staked funds.
3. If the `share_x` and `share_y` fields of the previously relayed message are identical to the incoming message,
then the message is a duplicate and MUST be discarded.
4. If none is found, then the message gets relayed.
An overview of the routing procedure and slashing is provided in Figure 2.
<!-- TODO: may consider [validator functions](https://github.com/libp2p/specs/tree/master/pubsub#topic-validation) or [extended validators](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#extended-validators) for the spam detection -->
![Figure 2: Publishing, Routing and Slashing workflow.](./images/rln-message-verification.png)
-------
# Payloads
### Payloads
Payloads are protobuf messages implemented using [protocol buffers v3](https://developers.google.com/protocol-buffers/).
Nodes MAY extend the [14/WAKU2-MESSAGE](/spec/14) with a `rate_limit_proof` field to indicate that their message is not spam.
Nodes MAY extend the [14/WAKU2-MESSAGE](../14/message.md) with a `rate_limit_proof` field to indicate that their message is not spam.
```diff
@@ -175,51 +217,52 @@ message WakuMessage {
optional uint32 version = 3;
optional sint64 timestamp = 10;
optional bool ephemeral = 31;
+ optional bytes rate_limit_proof = 21;
RateLimitProof rate_limit_proof = 21;
}
```
## WakuMessage
#### WakuMessage
`rate_limit_proof` holds the information required to prove that the message owner has not exceeded the message rate limit.
## RateLimitProof
#### RateLimitProof
Below is the description of the fields of `RateLimitProof` and their types.
| Parameter | Type | Description |
| ----: | ----------- | ----------- |
| `proof` | array of 256 bytes | the zkSNARK proof as explained in the [Publishing process](##Publishing) |
| `proof` | array of 256 bytes uncompressed or 128 bytes compressed | the zkSNARK proof as explained in the [Publishing process](##Publishing) |
| `merkle_root` | array of 32 bytes in little-endian order | the root of membership group Merkle tree at the time of publishing the message |
| `share_x` and `share_y`| array of 32 bytes each | Shamir secret shares of the user's secret identity key `sk` . `share_x` is the Poseidon hash of the `WakuMessage`'s `payload` concatenated with its `contentTopic` . `share_y` is calculated using [Shamir secret sharing scheme](/spec/32) | <!-- todo specify the poseidon hash setting -->
| `nullifier` | array of 32 bytes | internal nullifier derived from `epoch` and peer's `sk` as explained in [RLN construct](/spec/32)|
| `share_x` and `share_y`| array of 32 bytes each | Shamir secret shares of the user's secret identity key `sk` . `share_x` is the Poseidon hash of the `WakuMessage`'s `payload` concatenated with its `contentTopic` . `share_y` is calculated using [Shamir secret sharing scheme](../../../../vac/32/rln-v1.md) |
| `nullifier` | array of 32 bytes | internal nullifier derived from `epoch` and peer's `sk` as explained in [RLN construct](../../../../vac/32/rln-v1.md)|
# Recommended System Parameters
The system parameters are summarized in the following table, and the recommended values for a subset of them are presented next.
### Recommended System Parameters
The system parameters are summarized in the following table, and the RECOMMENDED values for a subset of them are presented next.
| Parameter | Description |
| ----: |----------- |
| `period` | the length of `epoch` in seconds |
| `staked_fund` | the amount of wei to be staked by peers at the registration |
| `staked_fund` | the amount of funds to be staked by peers at the registration |
| `reward_portion` | the percentage of `staked_fund` to be rewarded to the slashers |
| `max_epoch_gap` | the maximum allowed gap between the `epoch` of a routing peer and the incoming message |
| `acceptable_root_window_size` | The maximum number of past Merkle roots to store |
## Epoch Length
#### Epoch Length
A sensible value for the `period` depends on the application for which the spam protection is going to be used.
For example, while the `period` of `1` second i.e., messaging rate of `1` per second, might be acceptable for a chat application, might be too low for communication among Ethereum network validators.
For example, while the `period` of `1` second i.e.,
messaging rate of `1` per second, might be acceptable for a chat application,
might be too low for communication among Ethereum network validators.
One should look at the desired throughput of the application to decide on a proper `period` value.
In the proof of concept implementation of `17/WAKU2-RLN-RELAY` protocol which is available in [nim-waku](https://github.com/status-im/nim-waku), the `period` is set to `1` second.
Nevertheless, this value is also subject to change depending on user experience.
## Maximum Epoch Gap
We discussed in the [Routing](#routing) section that the gap between the epoch observed by the routing peer and the one attached to the incoming message should not exceed a threshold denoted by `max_epoch_gap` .
The value of `max_epoch_gap` can be measured based on the following factors.
#### Maximum Epoch Gap
We discussed in the [Routing](#routing) section that the gap between the epoch observed by the routing peer and
the one attached to the incoming message should not exceed a threshold denoted by `max_epoch_gap`.
The value of `max_epoch_gap` can be measured based on the following factors.
- Network transmission delay `Network_Delay`: the maximum time that it takes for a message to be fully disseminated in the GossipSub network.
- Clock asynchrony `Clock_Asynchrony`: The maximum difference between the Unix epoch clocks perceived by network peers which can be due to clock drifts.
With a reasonable approximation of the preceding values, one can set `max_epoch_gap` as
`max_epoch_gap` $= \lceil \frac{\text{Network Delay} + \text{Clock Asynchrony}}{\text{Epoch Length}}\rceil$ where `period` is the length of the `epoch` in seconds.
With a reasonable approximation of the preceding values, one can set `max_epoch_gap` as
`max_epoch_gap` $= \lceil \frac{\text{Network Delay} + \text{Clock Asynchrony}}{\text{Epoch Length}}\rceil$ where `period` is the length of the `epoch` in seconds.
`Network_Delay` and `Clock_Asynchrony` MUST have the same resolution as `period` .
By this formulation, `max_epoch_gap` indeed measures the maximum number of `epoch`s that can elapse since a message gets routed from its origin to all the other peers in the network.
@@ -234,14 +277,16 @@ By this formulation, `acceptable_root_window_size` will provide a lower bound of
The `acceptable_root_window_size` should indicate how many blocks may have been mined during the time it takes for a peer to receive a message.
This formula represents a lower bound of the number of acceptable roots.
# Copyright
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
# References
## References
1. [RLN documentation](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view)
2. [Public inputs to the RLN circuit](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Public-Inputs)
3. [Shamir secret sharing scheme used in RLN](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Linear-Equation-amp-SSS)
4. [RLN internal nullifier](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Nullifiers)
1. [`11/WAKU2-RELAY`](../11/relay.md)
2. [RLN](../../../../vac/32/rln-v1.md)
3. [14/WAKU2-MESSAGE](../14/message.md)
4. [RLN documentation](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view)
5. [Public inputs to the RLN circuit](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Public-Inputs)
6. [Shamir secret sharing scheme used in RLN](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Linear-Equation-amp-SSS)
7. [RLN internal nullifier](https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Nullifiers)

View File

@@ -3,9 +3,10 @@ slug: 19
title: 19/WAKU2-LIGHTPUSH
name: Waku v2 Light Push
status: draft
editor: Oskar Thorén <oskarth@titanproxy.com>
editor: Hanno Cornelius <hanno@status.im>
contributors:
- Daniel Kaiser <danielkaiser@status.im>
- Oskar Thorén <oskarth@titanproxy.com>
---
**Protocol identifier**: `/vac/waku/lightpush/2.0.0-beta1`
@@ -45,13 +46,13 @@ message PushRPC {
Nodes that respond to `PushRequests` MUST either
relay the encapsulated message via [11/WAKU2-RELAY](../11/relay.md) protocol on the specified `pubsub_topic`,
or forward the `PushRequest` via 19/LIGHTPUSH on a [44/WAKU2-DANDELION](https://github.com/waku-org/specs/blob/waku-RFC/standards/application/dandelion.md) stem.
or forward the `PushRequest` via 19/LIGHTPUSH on a [WAKU2-DANDELION](https://github.com/waku-org/specs/blob/waku-RFC/standards/application/dandelion.md) stem.
If they are unable to do so for some reason, they SHOULD return an error code in `PushResponse`.
## Security Considerations
Since this can introduce an amplification factor, it is RECOMMENDED for the node relaying to the rest of the network to take extra precautions.
This can be done by rate limiting via [17/WAKU2-RLN-RELAY](https://rfc.vac.dev/spec/17/).
This can be done by rate limiting via [17/WAKU2-RLN-RELAY](../17/rln-relay.md).
Note that the above is currently not fully implemented.
@@ -62,5 +63,5 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
## References
* [11/WAKU2-RELAY](../11/relay.md)
* [44/WAKU2-DANDELION](https://github.com/waku-org/specs/blob/waku-RFC/standards/application/dandelion.md)
* [WAKU2-DANDELION](https://github.com/waku-org/specs/blob/waku-RFC/standards/application/dandelion.md)
* [17/WAKU2-RLN-RELAY](../17/rln-relay.md)

View File

@@ -52,7 +52,7 @@ This also increases decentralization.
`33/WAKU2-DISCV5` spans a discovery network isolated from the Ethereum Discovery v5 network.
Another simple solution would be taking part in the Ethereum Discovery network, and filtering Waku nodes based on whether they support [31/WAKU2-ENR](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/enr.md).
Another simple solution would be taking part in the Ethereum Discovery network, and filtering Waku nodes based on whether they support [WAKU2-ENR](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/enr.md).
This solution is more resilient towards eclipse attacks.
However, this discovery method is very inefficient for small percentages of Waku nodes (see [estimation](https://forum.vac.dev/t/waku-v2-discv5-roadmap-discussion/121/8)).
It boils down to random walk discovery and does not offer a O(log(n)) hop bound.
@@ -157,7 +157,7 @@ Properly protecting against eclipse attacks is challenging and raises research q
1. [10/WAKU2](../10/waku2.md)
1. [11/WAKU2-RELAY](../11/relay.md)
1. [`31/WAKU2-ENR`](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/enr.md)
1. [`WAKU2-ENR`](https://github.com/waku-org/specs/blob/waku-RFC/standards/core/enr.md)
1. [Node Discovery Protocol v5 (`discv5`)](https://github.com/ethereum/devp2p/blob/master/discv5/discv5.md)
1. [`discv5` semantics](https://github.com/ethereum/devp2p/blob/master/discv5/discv5-theory.md).
1. [`discv5` wire protocol](https://github.com/ethereum/devp2p/blob/master/discv5/discv5-wire.md)

View File

@@ -697,7 +697,7 @@ This list has this format:
### `extern int waku_content_topic(char* applicationName, unsigned int applicationVersion, char* contentTopicName, char* encoding, WakuCallBack onOkCb)`
Create a content topic string according to [RFC 23](https://rfc.vac.dev/spec/23/).
Create a content topic string according to [RFC 23](../../../informational/23/topics.md).
**Parameters**
@@ -710,14 +710,14 @@ Create a content topic string according to [RFC 23](https://rfc.vac.dev/spec/23/
**Returns**
`int` with a status code. Possible values:
- 0 - The operation was completed successfuly. `onOkCb` will receive the content topic formatted according to [RFC 23](https://rfc.vac.dev/spec/23/): `/{application-name}/{version-of-the-application}/{content-topic-name}/{encoding}`
- 0 - The operation was completed successfuly. `onOkCb` will receive the content topic formatted according to [RFC 23](../../../informational/23/topics.md): `/{application-name}/{version-of-the-application}/{content-topic-name}/{encoding}`
- 1 - The operation failed for any reason.
- 2 - The function is missing the `onOkCb` callback
### `extern int waku_pubsub_topic(char* name, char* encoding, WakuCallBack onOkCb)`
Create a pubsub topic string according to [RFC 23](https://rfc.vac.dev/spec/23/).
Create a pubsub topic string according to [RFC 23](../../../informational/23/topics.md).
**Parameters**
@@ -728,13 +728,13 @@ Create a pubsub topic string according to [RFC 23](https://rfc.vac.dev/spec/23/)
**Returns**
`int` with a status code. Possible values:
- 0 - The operation was completed successfuly. `onOkCb` will get populated with a pubsub topic formatted according to [RFC 23](https://rfc.vac.dev/spec/23/): `/waku/2/{topic-name}/{encoding}`
- 0 - The operation was completed successfuly. `onOkCb` will get populated with a pubsub topic formatted according to [RFC 23](../../../informational/23/topics.md): `/waku/2/{topic-name}/{encoding}`
- 1 - The operation failed for any reason.
- 2 - The function is missing the `onOkCb` callback
### `extern int waku_default_pubsub_topic(WakuCallBack onOkCb)`
Returns the default pubsub topic used for exchanging waku messages defined in [RFC 10](https://rfc.vac.dev/spec/10/).
Returns the default pubsub topic used for exchanging waku messages defined in [RFC 10](../10/waku2.md).
**Parameters**
1. `WakuCallBack onOkCb`: callback to be executed if the function is succesful
@@ -752,7 +752,7 @@ Publish a message using Waku Relay.
**Parameters**
1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type).
1. `char* messageJson`: JSON string containing the [Waku Message](../14/message.md) as [`JsonMessage`](#jsonmessage-type).
2. `char* pubsubTopic`: pubsub topic on which to publish the message.
If `NULL`, it uses the default pubsub topic.
3. `int timeoutMs`: Timeout value in milliseconds to execute the call.
@@ -1089,7 +1089,7 @@ Publish a message using Waku Lightpush.
**Parameters**
1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type).
1. `char* messageJson`: JSON string containing the [Waku Message](../14/message.md) as [`JsonMessage`](#jsonmessage-type).
2. `char* pubsubTopic`: pubsub topic on which to publish the message.
If `NULL`, it uses the default pubsub topic.
3. `char* peerID`: Peer ID supporting the lightpush protocol.
@@ -1177,7 +1177,7 @@ Encrypt a message using symmetric encryption and optionally sign the message
**Parameters**
1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type).
1. `char* messageJson`: JSON string containing the [Waku Message](../14/message.md) as [`JsonMessage`](#jsonmessage-type).
2. `char* symmetricKey`: hex encoded secret key to be used for encryption.
3. `char* optionalSigningKey`: hex encoded private key to be used to sign the message.
4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful
@@ -1198,7 +1198,7 @@ Encrypt a message using asymmetric encryption and optionally sign the message
**Parameters**
1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type).
1. `char* messageJson`: JSON string containing the [Waku Message](../14/message.md) as [`JsonMessage`](#jsonmessage-type).
2. `char* publicKey`: hex encoded public key to be used for encryption.
3. `char* optionalSigningKey`: hex encoded private key to be used to sign the message.
4. `WakuCallBack onOkCb`: callback to be executed if the function is succesful
@@ -1221,7 +1221,7 @@ Decrypt a message using a symmetric key
**Parameters**
1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type).
1. `char* messageJson`: JSON string containing the [Waku Message](../14/message.md) as [`JsonMessage`](#jsonmessage-type).
2. `char* symmetricKey`: 32 byte symmetric key hex encoded.
3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful
4. `WakuCallBack onErrCb`: callback to be executed if the function fails
@@ -1249,7 +1249,7 @@ Decrypt a message using a secp256k1 private key
**Parameters**
1. `char* messageJson`: JSON string containing the [Waku Message](https://rfc.vac.dev/spec/14/) as [`JsonMessage`](#jsonmessage-type).
1. `char* messageJson`: JSON string containing the [Waku Message](../14/message.md) as [`JsonMessage`](#jsonmessage-type).
2. `char* privateKey`: secp256k1 private key hex encoded.
3. `WakuCallBack onOkCb`: callback to be executed if the function is succesful
4. `WakuCallBack onErrCb`: callback to be executed if the function fails

View File

@@ -0,0 +1,320 @@
---
slug: 64
title: 64/WAKU2-NETWORK
name: Waku v2 Network
status: draft
category: Best Current Practice
tags: waku/application
editor: Hanno Cornelius <hanno@status.im>
contributors:
---
## Abstract
This specification describes an opinionated deployment of [10/WAKU2](../10/waku2.md) protocols to form a coherent and
shared decentralized messaging network that is open-access,
useful for generalized messaging, privacy-preserving, scalable and
accessible even to resource-restricted devices.
We'll refer to this opinionated deployment simply as
_the public Waku Network_, _the Waku Network_ or, if the context is clear, _the network_
in the rest of this document.
## Theory / Semantics
### Routing protocol
The Waku Network is built on the [17/WAKU2-RLN-RELAY](../17/rln-relay.md) routing protocol,
which in turn is an extension of [11/WAKU2-RELAY](../11/relay.md) with spam protection measures.
### Network shards
Traffic in the Waku Network is sharded into eight [17/WAKU2-RLN-RELAY](../17/rln-relay.md) pubsub topics.
Each pubsub topic is named according to the static shard naming format
defined in [WAKU2-RELAY-SHARDING](https://github.com/waku-org/specs/blob/master/standards/core/relay-sharding.md)
with:
* `<cluster_id>` set to `1`
* `<shard_number>` occupying the range `0` to `7`.
In other words, the Waku Network is a [17/WAKU2-RLN-RELAY](../17/rln-relay.md) network
routed on the combination of the eight pubsub topics:
```
/waku/2/rs/1/0
/waku/2/rs/1/1
...
/waku/2/rs/1/7
```
A node MUST use [WAKU-METADATA](https://github.com/waku-org/specs/blob/master/standards/core/metadata.md) protocol to identify the `<cluster_id>` that every
inbound/outbound peer that attempts to connect supports. In any of the following cases, the node MUST trigger a disconnection:
* [WAKU-METADATA](https://github.com/waku-org/specs/blob/master/standards/core/metadata.md) dial fails.
* [WAKU-METADATA](https://github.com/waku-org/specs/blob/master/standards/core/metadata.md) reports an empty `<cluster_id>`.
* [WAKU-METADATA](https://github.com/waku-org/specs/blob/master/standards/core/metadata.md) reports a `<cluster_id>` different than `1`.
## Roles
There are two distinct roles evident in the network, those of:
1) nodes, and
2) applications.
### Nodes
Nodes are the individual software units
using [10/WAKU2](../10/waku2.md) protocols to form a p2p messaging network.
Nodes, in turn, can participate in a shard as full relayers, i.e. _relay nodes_,
or by running a combination of protocols suitable for resource-restricted environments,
i.e. _non-relay nodes_.
Nodes can also provide various services to the network,
such as storing historical messages or protecting the network against spam.
See the section on [default services](#default-services) for more.
#### Relay nodes
Relay nodes MUST follow [17/WAKU2-RLN-RELAY](../17/rln-relay.md)
to route messages to other nodes in the network
for any of the pubsub topics [defined as the Waku Network shards](#network-shards).
Relay nodes MAY choose to subscribe to any of these shards,
but MUST be subscribed to at least one defined shard.
Each relay node SHOULD be subscribed to as many shards as it has resources to support.
If a relay node supports an encapsulating application,
it SHOULD be subscribed to all the shards servicing that application.
If resource restrictions prevent a relay node from servicing all shards used by the encapsulating application,
it MAY choose to support some shards as a non-relay node.
#### Bootstrapping and discovery
Nodes MAY use any method to bootstrap connection to the network,
but it is RECOMMENDED that each node retrieves a list of bootstrap peers to connect to using [EIP-1459 DNS-based discovery](https://eips.ethereum.org/EIPS/eip-1459).
Relay nodes SHOULD use [33/WAKU2-DISCV5](../33/discv5.md) to continually discover other peers in the network.
Each relay node MUST encode its supported shards into its discoverable ENR,
as described in [WAKU2-RELAY-SHARDING](https://github.com/waku-org/specs/blob/master/standards/core/relay-sharding.md/#discovery).
The ENR MUST be updated if the set of supported shards change.
A node MAY choose to ignore discovered peers that do not support any of the shards in its own subscribed set.
#### Transports
Relay nodes MUST follow [10/WAKU2](../10/waku2.md) specifications with regards to supporting different transports.
If TCP transport is available, each relay node MUST support it as transport for both dialing and listening.
In addition, a relay node SHOULD support secure websockets for bidirectional communication streams,
for example to allow connections from and to web browser-based clients.
A relay node MAY support unsecure websockets if required by the application or running environment.
#### Default services
For each supported shard,
each relay node SHOULD enable and support the following protocols as a service node:
1. [12/WAKU2-FILTER](../12/filter.md) to allow resource-restricted peers to subscribe to messages matching a specific content filter.
2. [13/WAKU2-STORE](../13/store.md) to allow other peers to request historical messages from this node.
3. [19/WAKU2-LIGHTPUSH](../19/lightpush.md) to allow resource-restricted peers to request publishing a message to the network on their behalf.
4. [WAKU2-PEER-EXCHANGE](https://github.com/waku-org/specs/blob/master/standards/core/peer-exchange.md) to allow resource-restricted peers to discover more peers in a resource efficient way.
#### Store service nodes
Each relay node SHOULD support [13/WAKU2-STORE](../13/store.md) as a store service node,
for each supported shard.
The store SHOULD be configured to retain at least `12` hours of messages per supported shard.
Store service nodes SHOULD only store messages with a valid [`rate_limit_proof`](#message-attributes) attribute.
#### Non-relay nodes
Nodes MAY opt out of relay functionality on any network shard
and instead request services from relay nodes as clients
using any of the defined service protocols:
1. [12/WAKU2-FILTER](../12/filter.md) to subscribe to messages matching a specific content filter.
2. [13/WAKU2-STORE](../13/store.md) to request historical messages matching a specific content filter.
3. [19/WAKU2-LIGHTPUSH](../19/lightpush.md) to request publishing a message to the network.
4. [WAKU2-PEER-EXCHANGE](https://github.com/waku-org/specs/blob/master/standards/core/peer-exchange.md) to discover more peers in a resource efficient way.
#### Store client nodes
Nodes MAY request historical messages from [13/WAKU2-STORE](../13/store.md) service nodes as store clients.
A store client SHOULD discard any messages retrieved from a store service node that do not contain a valid [`rate_limit_proof`](#message-attributes) attribute.
The client MAY consider service nodes returning messages without a valid [`rate_limit_proof`](#message-attributes) attribute as untrustworthy.
The mechanism by which this may happen is currently underdefined.
### Applications
Applications are the higher-layer projects or platforms that make use of the generalized messaging capability of the network.
In other words, an application defines a payload used in the various [10/WAKU2](../10/waku2.md) protocols.
Any participant in an application SHOULD make use of an underlying node in order to communicate on the network.
Applications SHOULD make use of an [autosharding](#autosharding) API
to allow the underlying node to automatically select the target shard on the Waku Network.
See the section on [autosharding](#autosharding) for more.
## RLN rate-limiting
The [17/WAKU2-RLN-RELAY](../17/rln-relay.md) protocol uses [32/RLN-V1](../../../../vac/32/rln-v1.md) proofs
to ensure that a pre-agreed rate limit is not exceeded by any publisher.
While the network is under capacity,
individual relayers MAY choose to freely route messages without RLN proofs
up to a discretionary bandwidth limit,
after which messages without proofs MUST be discarded by relay nodes.
This bandwidth limit SHOULD be enforced using a [bandwidth validation mechanism](#free-bandwidth-exceeded) separate from a RLN rate-limiting.
This implies that quality of service and reliability is significantly lower for messages without proofs
and at times of high network utilization these messages may not be relayed at all.
### RLN Parameters
For the Waku Network,
the `epoch` is set to `1` second
and the maximum number of messages published per `epoch` is limited to `1` per publisher.
The `max_epoch_gap` is set to `20` seconds,
meaning that validators (relay nodes),
MUST _reject_ messages with an `epoch` more than 20 seconds into the past or
future compared to the validator's own clock.
All nodes, validators and publishers,
SHOULD use Network Time Protocol (NTP) to synchronize their own clocks,
thereby ensuring valid timestamps for proof generation and validation.
### Memberships
Each publisher to the Waku Network SHOULD register an RLN membership
with one of the RLN storage contracts
moderated in the Sepolia registry contract with address [0xF1935b338321013f11068abCafC548A7B0db732C](https://sepolia.etherscan.io/address/0xF1935b338321013f11068abCafC548A7B0db732C#code).
Initial memberships are registered in the Sepolia RLN storage contract with address [0x58322513A35a8f747AF5A385bA14C2AbE602AA59](https://sepolia.etherscan.io/address/0x58322513A35a8f747AF5A385bA14C2AbE602AA59#code).
RLN membership setup and registration MUST follow [17/WAKU2-RLN-RELAY](../17/rln-relay.md/#setup-and-registration),
with the `staked_fund` set to `0`.
In other words, the Waku Network does not use RLN staking.
### RLN Proofs
Each RLN member MUST generate and attach an RLN proof to every published message
as described in [17/WAKU2-RLN-RELAY](../17/rln-relay.md/#publishing).
Slashing is not implemented for the Waku Network.
Instead, validators will penalise peers forwarding messages exceeding the rate limit
as specified for [the rate-limiting validation mechanism](#rate-limit-exceeded).
This incentivizes all relay nodes to validate RLN proofs
and reject messages violating rate limits
in order to continue participating in the network.
## Network traffic
All payload on the Waku Network MUST be encapsulated in a [14/WAKU2-MESSAGE](../14/message.md)
with rate limit proof extensions defined for [17/WAKU2-RLN-RELAY](../17/rln-relay.md/#payloads).
Each message on the Waku Network SHOULD be validated by each relayer,
according to the rules discussed under [message validation](#message-validation).
### Message Attributes
- The mandatory `payload` attribute MUST contain the message data payload as crafted by the application.
- The mandatory `content_topic` attribute MUST specify a string identifier that can be used for content-based filtering.
This is also crafted by the application.
See [Autosharding](#autosharding) for more on the content topic format.
- The optional `meta` attribute MAY be omitted.
If present, will form part of the message uniqueness vector described in [14/WAKU2-MESSAGE](../14/message.md).
- The optional `version` attribute SHOULD be set to `0`. It MUST be interpreted as `0` if not present.
- The mandatory `timestamp` attribute MUST contain the Unix epoch time at which the message was generated by the application.
The value MUST be in nanoseconds.
It MAY contain a fudge factor of up to 1 seconds in either direction to improve resistance to timing attacks.
- The optional `ephemeral` attribute MUST be set to `true` if the message should not be persisted by the Waku Network.
- The optional `rate_limit_proof` attribute SHOULD be populated with the RLN proof as set out in [RLN Proofs](#rln-proofs).
Messages with this field unpopulated MAY be discarded from the network by relayers.
This field MUST be populated if the message should be persisted by the Waku Network.
### Message Size
Any [14/WAKU2-MESSAGE](../14/message.md) published to the network MUST NOT exceed an absolute maximum size of `150` kilobytes.
This limit applies to the entire message after protobuf serialization, including attributes.
It is RECOMMENDED not to exceed an average size of `4` kilobytes for [14/WAKU2-MESSAGE](../14/message.md) published to the network.
### Message Validation
Relay nodes MUST apply [gossipsub v1.1 validation](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#extended-validators) to each relayed message and
SHOULD apply all of the rules set out in the section below to determine the validity of a message.
Validation has one of three outcomes,
repeated here from the [gossipsub specification](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#extended-validators) for ease of reference:
1. Accept - the message is considered valid and it MUST be delivered and forwarded to the network.
2. Reject - the message is considered invalid, MUST be rejected and SHOULD trigger a gossipsub scoring penalty against the transmitting peer.
3. Ignore - the message SHOULD NOT be delivered and forwarded to the network, but this MUST NOT trigger a gossipsub scoring penalty against the transmitting peer.
The following validation rules are defined:
#### Decoding failure
If a message fails to decode as a valid [14/WAKU2-MESSAGE](../14/message.md),
the relay node MUST _reject_ the message.
This SHOULD trigger a penalty against the transmitting peer.
#### Invalid timestamp
If a message has a timestamp deviating by more than `20` seconds
either into the past or the future
when compared to the relay node's internal clock,
the relay node MUST _reject_ the message.
This allows for some deviation between internal clocks,
network routing latency and
an optional [fudge factor when timestamping new messages](#message-attributes).
#### Free bandwidth exceeded
If a message contains no RLN proof
and the current bandwidth utilization on the shard the message was published to
equals or exceeds `1` Mbps,
the relay node SHOULD _ignore_ the message.
#### Invalid RLN epoch
If a message contains an RLN proof
and the `epoch` attached to the proof deviates by more than `max_epoch_gap` seconds
from the relay node's own `epoch`,
the relay node MUST _reject_ the message.
`max_epoch_gap` is [set to `20` seconds](#rln-parameters) for the Waku Network.
#### Invalid RLN proof
If a message contains an RLN proof
and the zero-knowledge proof is invalid
according to the verification process described in [32/RLN-V1](../../../../vac/32/rln-v1.md),
the relay node MUST _ignore_ the message.
#### Rate limit exceeded
If a message contains an RLN proof
and the relay node detects double signaling
according to the verification process described in [32/RLN-V1](../../../../vac/32/rln-v1.md),
the relay node MUST _reject_ the message
for violating the agreed rate limit of `1` message every `1` second.
This SHOULD trigger a penalty against the transmitting peer.
## Autosharding
Nodes in the Waku Network SHOULD allow encapsulating applications to use autosharding,
as defined in [WAKU2-RELAY-SHARDING](https://github.com/waku-org/specs/blob/master/standards/core/relay-sharding.md/#automatic-sharding)
by automatically determining the appropriate pubsub topic
from the list [of defined Waku Network shards](#network-shards).
This allows the application to omit the target pubsub topic
when invoking any Waku protocol function.
Applications using autosharding MUST use content topics in the format
defined in [WAKU2-RELAY-SHARDING](https://github.com/waku-org/specs/blob/master/standards/core/relay-sharding.md/#content-topics-format-for-autosharding)
and SHOULD use the short length format:
```
/{application-name}/{version-of-the-application}/{content-topic-name}/{encoding}
```
When an encapsulating application makes use of autosharding
the underlying node MUST determine the target pubsub topic(s)
from the content topics provided by the application
using the hashing mechanism defined in [WAKU2-RELAY-SHARDING](https://github.com/waku-org/specs/blob/master/standards/core/relay-sharding.md/#automatic-sharding).
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
* [10/WAKU2](../10/waku2.md)
* [17/WAKU2-RLN-RELAY](../17/rln-relay.md)
* [11/WAKU2-RELAY](../11/relay.md)
* [WAKU2-RELAY-SHARDING](../../core/relay-sharding.md)
* [WAKU-METADATA](https://github.com/waku-org/specs/blob/master/standards/core/metadata.md)
* [EIP-1459 DNS-based discovery](https://eips.ethereum.org/EIPS/eip-1459)
* [33/WAKU2-DISCV5](../33/discv5.md)
* [12/WAKU2-FILTER](../12/filter.md)
* [13/WAKU2-STORE](../13/store.md)
* [19/WAKU2-LIGHTPUSH](../19/lightpush.md)
* [34/WAKU2-PEER-EXCHANGE](../../core/peer-exchange.md)
* [32/RLN-V1](../../../../vac/32/rln-v1.md)
* [14/WAKU2-MESSAGE](../14/message.md)
* [gossipsub v1.1 validation](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#extended-validators)
* [WAKU2-RELAY-SHARDING](https://github.com/waku-org/specs/blob/master/standards/core/relay-sharding.md/)
*

View File

@@ -0,0 +1,51 @@
---
slug: 66
title: 66/WAKU2-METADATA
name: Waku Metadata Protocol
status: draft
editor: Alvaro Revuelta <alrevuelta@status.im>
contributors:
---
## Abstract
This specification describes the metadata that can be associated with a [10/WAKU2](../10/waku2.md) node.
## Metadata Protocol
Waku specifies a req/resp protocol that provides information about the node's medatadata.
Such metadata is meant to be used by the node to decide if a peer is worth connecting or not.
The node that makes the request, includes its metadata so that the receiver is aware of it,
without requiring an extra interaction.
The parameters are the following:
* `clusterId`: Unique identifier of the cluster that the node is running in.
* `shards`: Shard indexes that the node is subscribed to.
***Protocol Identifier***
/vac/waku/metadata/1.0.0
### Request
```proto
message WakuMetadataRequest {
optional uint32 cluster_id = 1;
repeated uint32 shards = 2;
}
```
### Response
```proto
message WakuMetadataResponse {
optional uint32 cluster_id = 1;
repeated uint32 shards = 2;
}
```
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
## References
- [10/WAKU2](../10/waku2.md)

View File

@@ -36,7 +36,7 @@ This protocol needs to advertise the `waku/1` [capability](https://ethereum.gitb
### Gossip based routing
In Whisper, envelopes are gossiped between peers. Whisper is a form of rumor-mongering protocol that works by flooding to its connected peers based on some factors. Envelopes are eligible for retransmission until their TTL expires. A node SHOULD relay envelopes to all connected nodes if an envelope matches their PoW and bloom filter settings. If a node works in light mode, it MAY choose not to forward envelopes. A node MUST NOT send expired envelopes, unless the envelopes are sent as a [8/WAKU-MAIL](../../application/8/mail.md) response. A node SHOULD NOT send an envelope to a peer that it has already sent before.
In Whisper, envelopes are gossiped between peers. Whisper is a form of rumor-mongering protocol that works by flooding to its connected peers based on some factors. Envelopes are eligible for retransmission until their TTL expires. A node SHOULD relay envelopes to all connected nodes if an envelope matches their PoW and bloom filter settings. If a node works in light mode, it MAY choose not to forward envelopes. A node MUST NOT send expired envelopes, unless the envelopes are sent as a [8/WAKU-MAIL](../8/mail.md) response. A node SHOULD NOT send an envelope to a peer that it has already sent before.
### Maximum Packet Size
@@ -343,7 +343,7 @@ The drawback of sending message confirmations is that it increases the noise in
#### P2P Request
This packet is used for sending Dapp-level peer-to-peer requests, e.g. Waku Mail Client requesting historic (expired) envelopes from the [Waku Mail Server](../../application/8/mail.md).
This packet is used for sending Dapp-level peer-to-peer requests, e.g. Waku Mail Client requesting historic (expired) envelopes from the [Waku Mail Server](../8/mail.md).
#### P2P Message
@@ -353,7 +353,7 @@ This packet is used for sending the peer-to-peer envelopes, which are not suppos
This packet is used to indicate that all envelopes, requested earlier with a P2P Request packet (`0x7E`), have been sent via one or more P2P Message packets (`0x7F`).
The content of the packet is explained in the [Waku Mail Server](../../application/8/mail.md) specification.
The content of the packet is explained in the [Waku Mail Server](../8/mail.md) specification.
### Payload Encryption
@@ -373,7 +373,7 @@ Packet codes `0x7E` and `0x7F` may be used to implement Waku Mail Server and Cli
Waku supports multiple capabilities. These include light node, rate limiting and bridging of traffic. Here we list these capabilities, how they are identified, what properties they have and what invariants they must maintain.
Additionally there is the capability of a mailserver which is documented in its on [specification](../../application/8/mail.md).
Additionally there is the capability of a mailserver which is documented in its on [specification](../8/mail.md).
### Light node
@@ -452,7 +452,7 @@ It is desirable to have a strategy for maintaining forward compatibility between
## Appendix A: 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 vary depending on what capabilities are used. The security considerations for extra capabilities such as [mailservers](../../application/8/mail.md#security-considerations) can be found in their respective specifications.
There are several security considerations to take into account when running Waku. Chief among them are: scalability, DDoS-resistance and privacy. These also vary depending on what capabilities are used. The security considerations for extra capabilities such as [mailservers](../8/mail.md#security-considerations) can be found in their respective specifications.
### Scalability and UX

View File

@@ -9,7 +9,7 @@ contributors:
- Kim De Mey <kimdemey@status.im>
---
This specification describes the encryption, decryption and signing of the content in the [data field used in Waku](../../standards/core/6/waku1.md/#abnf-specification).
This specification describes the encryption, decryption and signing of the content in the [data field used in Waku](../6/waku1.md/#abnf-specification).
## Specification

View File

@@ -100,7 +100,7 @@ A mailserver client fetches archival envelopes from a mailserver through a direc
In this direct connection, the client discloses its IP/ID as well as the topics/ bloom filter it is interested in to the mailserver.
The collection of such information allows the mailserver to link clients' IP/IDs to their topic interests and build a profile for each client over time.
As such, the mailserver client has to trust the mailserver with this level of information.
A similar concern exists for the light nodes and their direct peers which is discussed in the security considerations of [6/WAKU1](/spec/7).
A similar concern exists for the light nodes and their direct peers which is discussed in the security considerations of [6/WAKU1](../6/waku1.md).
**Mailserver trusted connection:**

View File

@@ -46,7 +46,7 @@ In this section you will find objects used throughout the JSON RPC API.
#### Message
The message object represents a Waku message. Below you will find the description of the attributes contained in the message object. A message is the decrypted payload and padding of an [envelope](/spec/7) along with all of its metadata and other extra information such as the hash.
The message object represents a Waku message. Below you will find the description of the attributes contained in the message object. A message is the decrypted payload and padding of an [envelope](../7/data.md) along with all of its metadata and other extra information such as the hash.
| Field | Type | Description |
| ----: | :--: | ----------- |