minor edits

This commit is contained in:
Sergei Tikhomirov 2024-08-12 19:09:20 +02:00
parent 1fe5dfc65f
commit 7ff2c60167
No known key found for this signature in database
GPG Key ID: 6A1F8ED9D6538027

View File

@ -9,35 +9,33 @@ contributors:
## Abstract
This document specifies RLN membership management in the context of mainnet deployment of the RLN smart contract, in particular:
This document describes membership management for the RLN smart contract, in particular:
- membership-related contract functionality;
- contract parameters for the initial mainnet deployment;
- suggested parameters valued for the initial mainnet deployment;
- contract governance and upgradability.
We only consider contract functionality relevant for membership management.
The document might later evolve into a full-fledged contract specification.
This document currently only considers membership-related functionality.
It might later evolve into a full-fledged contract specification.
RLN is only deployed on Sepolia testnet ([source code](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol)) as of August 2024.
This document aims to outline the path to its mainnet deployment.
## Background
Rate-Limiting Nullifier (RLN) is a ZK-based gadget used in Waku.
RLN provides a privacy-preserving way to limit each user's burden on the network.
Rate-Limiting Nullifier (RLN) is a ZK-based gadget used for privacy-preserving rate limiting in Waku.
The RLN smart contract is the core element of RLN architecture.
Users interact with the contract to manage their memberships,
as well as to get the data necessary for proof generation and verification.
The smart contract stores the RLN tree that contains all currently existing memberships.
Users interact with the contract to manage their memberships
and to get the necessary data for proof generation and verification.
To relay a message:
- the sender MUST register a membership in a smart contract;
- the sender MUST attach a ZK-proof of membership to every message;
- each relaying node MUST relay a message unless:
- the message is committed to a different epoch than the current epoch; or
- the user has exceed their allowed rate limit for the current epoch; or
- the RLN proof fails to prove that the message sender holds a membership.
Sending messages is handled by Waku Relay nodes.
To send a message, the sender MUST attach a ZK-proof to the message.
A Relay node MUST relay a message unless:
- the message belongs to any epoch other than the current one; or
- the user has exceed their allowed rate limit for the current epoch; or
- the ZK-proof fails to prove that the sender holds a membership.
Sending messages is handled by Waku Relay nodes, not by the RLN smart contract.
The full specification of Relay node behavior is out of scope for this document.
RLN is only deployed on Sepolia testnet as of August 2024.
This document aims to outline the path to its mainnet deployment.
The full specification of Relay is out of scope for this document.
## Contract overview
@ -46,15 +44,7 @@ The contract MUST provide the following functionalities:
- extend a membership;
- withdraw a deposit.
Availability of membership-specific functionalities MUST be as follows:
| | Active | Grace Period | Expired | ErasedAwaitsWithdrawal | Erased |
| --------------------- | ------ | ------------ | ------- | ---------------------- | ------ |
| Send a message | Yes | Yes | Yes | No | No |
| Extend the membership | No | Yes | No | No | No |
| Withdraw the deposit | No | Yes | Yes | Yes | No |
Contract parameters and their RECOMMENDED values are as follows:
Contract parameters and their RECOMMENDED values for the initial mainnet deployment are as follows:
| Parameter | Symbol | Value | Units |
| ------------------------------------------- | --------- | ------- | ---------------------------------- |
@ -77,9 +67,9 @@ Any existing membership MUST always be in exactly one of the following states:
```mermaid
graph TD;
NonExistent --> |"register"| Active;
Active --> |"time `T` passed"| GracePeriod;
Active --> |"time T passed"| GracePeriod;
GracePeriod --> |"extend"| Active;
GracePeriod --> |"time `G` passed"| Expired;
GracePeriod --> |"time G passed"| Expired;
GracePeriod --> |"withdraw"| Erased;
Expired --> |"withdraw"| Erased;
Expired --> |"another membership reuses slot"| ErasedAwaitsWithdrawal;
@ -87,8 +77,9 @@ graph TD;
```
State updates triggered by a transaction MUST be applied immediately.
State updates defined by time progression MAY be applied lazily.
State updates triggered by a transaction (e.g., from _GracePeriod_ to _Active_ as a result of `extend`) MUST be applied immediately.
State updates defined by time progression (e.g., from _GracePeriod_ to _Expired_ after time `G`) MAY be applied lazily.
When providing any membership-specific functionality, the contract MUST:
- check whether the state of the membership involved is up-to-date;
- if necessary, update the membership state;
@ -96,51 +87,63 @@ When providing any membership-specific functionality, the contract MUST:
Memberships MUST be included in the RLN tree according to the following table:
| State | Included in the tree |
| ---------------------- | -------------------- |
| Active | Yes |
| GracePeriod | Yes |
| Expired | Yes |
| ErasedAwaitsWithdrawal | No |
| Erased | No |
| State | Included in the RLN tree |
| ------------------------ | ------------------------ |
| _Active_ | Yes |
| _GracePeriod_ | Yes |
| _Expired_ | Yes |
| _ErasedAwaitsWithdrawal_ | No |
| _Erased_ | No |
Memberships MUST NOT be transferable.
A user MAY use one Ethereum address to manage multiple memberships.
A user MAY use one Waku node to manage multiple memberships. ^1
A user MAY use one Waku node to manage multiple memberships. [^1]
[^1]: No Waku implementation supports managing multiple memberships from one node (as of August 2024).
## Contract functionalities
Availability of membership-specific functionalities MUST be as follows:
| | Active | GracePeriod | Expired | ErasedAwaitsWithdrawal | Erased |
| --------------------- | ------ | ----------- | ------- | ---------------------- | ------ |
| Send a message | Yes | Yes | Yes | No | No |
| Extend the membership | No | Yes | No | No | No |
| Withdraw the deposit | No | Yes | Yes | Yes | No |
Sending a message is included here for completeness,
although it is part of the Relay protocol and not the RLN contract.
### Register a membership
Membership registration is subject to the following conditions:
- if there are _Expired_ memberships in the contract, the new membership MUST overwrite an expired membership;
- if there are _Expired_ memberships in the RLN tree, the new membership MUST overwrite an _Expired_ membership;
- the new membership SHOULD overwrite the membership that had been _Expired_ for the longest time;
- if an _Expired_ membership A is overwritten by membership B:
- membership B MUST transition to _ErasedAwaitsWithdrawal_;
- if a new membership A overwrites an _Expired_ membership B:
- membership B MUST become _ErasedAwaitsWithdrawal_;
- the current total rate limit MUST be decremented by the rate limit of membership B;
- the contract MUST take all necessary steps to ensure that the holder of membership B can withdraw their deposit later;
- registration MUST fail if the total rate limit of _Active_, _GracePeriod_, and _Expired_ memberships, including the one being created, would exceed the limit;
- registration MUST fail if the requested rate limit for the new membership is lower than the minimal allowed rate limit;
- registration MUST fail if the total rate limit of _Active_, _GracePeriod_, and _Expired_ memberships, including the one being created, would exceed the maximum total rate;
- registration MUST fail if the requested rate limit for a new membership is lower than the minimal allowed rate limit;
- the user MUST lock-up a deposit to register a membership;
- the user MUST specify the rate limit of the new membership;
- the size of the deposit MUST be calculated depending on the requested rate limit;
- in case of successful registration:
- the new membership MUST be in the _Active_ state;
- the user MUST specify the rate limit of the new membership[^2];
- the size of the deposit MUST depend on the requested rate limit;
- in case of a successful registration:
- the new membership MUST become _Active_;
- the current total rate limit MUST be incremented by the rate limit of the new membership;
- a newly created membership MUST have an expiration time `T` and a grace period `G` (see RECOMMENDED parameter values below).
- a newly created membership MUST have an expiration time `T` and a grace period `G`.
[^2]: A user-facing application SHOULD suggest default values for rate limits for the user.
### Extend a membership
Extending a membership is subject to the following condition:
Extending a membership is subject to the following conditions:
- extension MUST fail if the membership is in any state other than _GracePeriod_;
- the membership holder MUST be able to extend their membership;
- any user except the membership holder MUST NOT be able to extend a membership;
- after a successful extension, the membership MUST become _Active_.
Owning a membership means controlling the private key from which the RLN commitment ID (i.e., public key) was derived.
Holding a membership means controlling the private key from which the RLN commitment ID (i.e., public key) was derived.
### Withdraw the deposit
@ -149,24 +152,22 @@ Deposit withdrawal is subject to the following conditions:
- any user except the membership holder MUST NOT be able to withdraw its deposit;
- a deposit MUST be withdrawn in full;
- a withdrawal MUST fail if the membership is not in _GracePeriod_, _Expired_, or _ErasedAwaitsWithdrawal_;
- any withdrawal MUST move the membership to _Erased_.
- a membership MUST become _Erased_ after withdrawal.
## Governance and upgradability
At initial mainnet deployment, the contract MUST have an _Owner_.
The _Owner_ MUST be able to change the values of all contract parameters.
The _Owner_ MUST be able to pause any of the following contract functionalities:
- register a membership;
- extend a membership;
- withdraw a deposit.
- register a membership;
- extend a membership;
- withdraw a deposit.
At some point, the _Owner_ SHOULD renounce their privileges, and the contract MUST become immutable.
Further upgrades, if necessary, SHOULD be done by deploying a new contract and migrating the membership set.
## Implementation Suggestions
The current version of the contract (RLNv2) is deployed on Sepolia testnet ([source code](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol)).
User-facing application SHOULD suggest a few rate limits (tiers) to simplify their users' choice.
The RECOMMENDED rate limits in a three-tier model are as follows:
- `20` messages per epoch as low-tier;
@ -195,30 +196,31 @@ The rationale for this limitation is to prevent an undesirable usage pattern whe
Memberships can only be extended during _GracePeriod_.
We do not allow extending an _Active_ membership.
The rationale is that if the _Owner_ changes some contract parameters (e.g., for security purposes),
The rationale is that if the contract _Owner_ changes some contract parameters (e.g., for security purposes),
users with extended memberships will not be affected by the changes for a long time.
### What if I don't extend my membership within its _GracePeriod_?
The user who does not extend their _GracePeriod_ membership, assumes the risk of the membership being overwritten at any moment.
We expect that most users would not want to take that risk and would either extend their memberships or withdraw their deposits.
The user who does not extend their _GracePeriod_ membership,
assume the risk of the membership being overwritten at any moment.
We expect that most users would not want to take that risk
and would either extend their memberships or withdraw their deposits.
### Can I send messages when my membership is _Expired_?
An _Expired_ membership allows sending messages for some time.
Sending messages is managed by Relay nodes, not by RLN contract.
The RLN proof that message senders provide to Relay nodes only proves whether the sender owns _some_ membership included in the RLN tree.
The sender cannot prove the state of that membership.
Sending messages is managed by Relay nodes.
The RLN proof that message senders provide to Relay nodes doesn't prove the state of that membership.
_Expired_ memberships are not erased from the tree proactively.
An _Expired_ membership is only erased when either a new membership overwrites it, or when its deposit is withdrawn.
An _Expired_ membership is only erased when either a new membership overwrites it,
or when its deposit is withdrawn.
After a membership is erased, it can no longer be used for sending messages.
### Will my deposit be slashed if I exceed the rate limit?
This specification does not involve slashing.
The aim of the deposit initially is to protect the network from denial-of-service attacks with bandwidth capping.
The current version of RLN does not involve slashing.
### Do I need an extra deposit to extend a membership?
@ -230,16 +232,13 @@ The opportunity cost of locked-up capital plus gas fees for extension transactio
Epoch length is a global parameter set in the smart contract.
Rate limits are defined in terms of the maximum allowed messages per epoch.
There is a trade-off between short and long epochs.
We chose an epoch length of `10` minutes as a reasonable middle-ground.
On the one hand, longer epochs allow for better accommodating short-term usage peaks.
Peaks tend to average out over longer time periods,
which allows us to reason about network utilization on a longer time scale.
On the other hand, long epochs increases memory requirements for Relay nodes.
Each message contains a nullifier that proves its validity in terms of RLN.
Each Relay node must keeps in memory a nullifier log for the current epoch.
We chose an epoch length of `10` minutes as a reasonable middle-ground.
Each nullifier plus metadata is `128` bytes (per message).
With a `10`-minute epoch, one high-tier user with a `1` message per second rate limit generates up to `600 * 128 / 1024 = 75 KiB` of nullifier log data per epoch.
This corresponds to:
@ -257,11 +256,11 @@ The minimal rate limit prevents an attack where someone registers a large number
### Are there bulk discounts for high-rate memberships?
For the initial mainnet deployment, membership price is linearly proportional to its rate limit.
For the initial mainnet deployment, there are no bulk discounts.
Membership price is linearly proportional to its rate limit.
We choose this pricing scheme for simplicity.
In other words, there are no bulk discounts.
High-rate memberships are arguably more efficient but can incentivize centralization.
Finding a pricing scheme with the right trade-off remains subject for future work.
Finding a pricing scheme with the right trade-off remains subject for future work, as
high-rate memberships are arguably more efficient but can incentivize centralization.
### Why only accept DAI?
@ -269,7 +268,7 @@ When choosing a token to accept, we considered the following criteria:
- a stablecoin, as USD-denominated pricing is familiar for users and requires no oracle;
- popular, high liquidity;
- preferably decentralized;
- with a reasonably good track record w.r.t. censorship.
- with a reasonably good anti-censorship track record.
Based on these criteria, we chose DAI for the initial mainnet deployment.
Other tokens may be added in the future.
@ -277,10 +276,11 @@ Other tokens may be added in the future.
## Security / Privacy Considerations
Issuing membership-specific transactions (e.g., membership extension and deposit withdrawal) publicly links it to an Ethereum address.
Note that this does not degrade the privacy of the relayed messages.
Note that this does not degrade the privacy of the relayed messages,
as message validation doesn't require the sender to disclose which membership they hold.
To produce an RLN proof, a message sender must obtain a Merkle proof for their RLN membership.
One way to obtain this proof is to request it from the RLN smart contract.
To produce an RLN proof, a message sender must obtain a Merkle proof that their membership belongs to the RLN tree.
One way to obtain this proof is to request it from the smart contract itself.
Requesting a proof through a third-party RPC provider may endanger the sender's privacy.
The provider would be able to link the requester's Ethereum address and the RLN membership with the corresponding API key.