specs/standards/core/rln-contract.md

14 KiB

title name category tags editor contributors
WAKU2-RLN-CONTRACT Waku2 RLN Contract Specification Standards Track
waku/core-protocol
Sergei Tikhomirov <sergei@status.im>

Abstract

This document specifies RLN membership management in the context of mainnet deployment of the RLN smart contract, in particular:

  • membership-related contract functionality;
  • contract parameters 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.

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. 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.

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 drop the message if:
    • the proof is invalid; or
    • the sender has exceeded their rate limit within the current epoch.

RLN is only deployed on Sepolia testnet as of August 2024. This document aims to outline the path to its mainnet deployment.

Membership lifecycle

Any existing membership MUST always be in exactly one of the following states:

  • Active;
  • GracePeriod;
  • Expired;
  • ErasedAwaitsWithdrawal;
  • Erased.
graph TD;
    NonExistent --> |"register"| Active;
    Active --> |"time `T` passed"| GracePeriod;
    GracePeriod --> |"extend"| Active;
    GracePeriod --> |"time `G` passed"| Expired;
    GracePeriod --> |"withdraw"| Erased;
    Expired --> |"withdraw"| Erased;
    Expired --> |"another membership reuses slot"| ErasedAwaitsWithdrawal;
    ErasedAwaitsWithdrawal --> |"withdraw"| Erased;

State updates triggered by a transaction MUST be applied immediately. State updates defined by time progression 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;
  • process the transaction in accordance with the up-to-date membership state.

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

Memberships MUST NOT be transferable. One Ethereum address MAY register multiple memberships. One Waku node MAY manage multiple memberships (this functionality is not yet implemented as of August 2024).

Contract functionalities

The contract MUST provide the following functionalities:

  • register a membership;
  • 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

Governance and upgradability

At initial mainnet deployment, the contract MUST have an Owner with the following additional functionalities:

  • change any of the modifiable parameters, as listed in the Parameter table;
  • disable any of the following contract functionalities:
    • register a membership;
    • extend a membership;
    • (TBD) 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.

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;
  • 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;
    • 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;
  • 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 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).

Send a message

Sending messages is handled by Waku Relay nodes, not by the RLN smart contract. For completeness, sending messages is mentioned here as the key Waku functionality. The full specification of Relay node behavior is out of scope for this document.

A Relay 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 owns an existing membership.

Extend a membership

Extending a membership is subject to the following condition:

  • 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.

Withdraw the deposit

Deposit withdrawal is subject to the following conditions:

  • the membership holder MUST be able to withdraw their deposit;
  • 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.

Implementation Suggestions

The current version of the contract (RLNv2) is deployed on Sepolia testnet (source code).

The RECOMMENDED parameter values for the initial mainnet deployment are listed in the following table. All parameter values MUST be modifiable by the contract Owner.

Parameter Symbol Value Units
Epoch length epoch 10 minutes
Maximum total rate limit of all memberships R_{max} 20000 messages per epoch
Minimal rate limit of one membership r_{min} 20 messages per epoch
Price of 1 message per epoch p_u 0.01 USD per one period of length T
Membership expiration term T 90 days
Membership grace period G 30 days
Accepted tokens DAI
Reference currency USD
Pricing function linear

Applications MAY suggest the following rate limits to their users:

  • 20 messages per epoch as low-tier;
  • 200 messages per epoch as mid-tier;
  • 600 messages per epoch as high-tier.

The user-facing application SHOULD save the expiration date in its local keystore during membership registration, and notify the user when their membership is about to expire.

Q&A

Why can't I withdraw a deposit from an Active membership?

The rationale for this limitation is to prevent an undesirable usage pattern where users make deposits and withdrawals in short succession.

Why can't I extend an Active membership?

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), 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.

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.

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. 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?

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?

Membership extension requires no additional deposit. The opportunity cost of locked-up capital plus gas fees for extension transactions make extensions non-free, which is sufficient for the initial mainnet deployment.

Why this particular epoch length?

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.

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:

  • for 1000 users: approximately 73 MiB;
  • for 10 thousand users: approximately 732 MiB.

Why is there a cap on the total rate limit?

Total network bandwidth is a limited resource. We want to cap the total rate limit, at least in the initial mainnet deployment, to avoid overstretching the network's capabilities.

Why is there a minimal rate limit?

The minimal rate limit prevents an attack where someone registers a large number of memberships with a tiny rate limit each, causing the RLN tree to contain too many elements.

Are there bulk discounts for high-rate memberships?

For the initial mainnet deployment, 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.

Why only accept DAI?

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.

Based on these criteria, we chose DAI for the initial mainnet deployment. 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.

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. 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.

Copyright and related rights waived via CC0.

References