-
Notifications
You must be signed in to change notification settings - Fork 0
Description
TLDR: Proposal on how to distribute RLN membership fees to the node operators that submit the correct Merkle root
of the messages sent during a superepoch.
Problem statement
Waku has chosen Rate Limiting Nullifiers to rate-limit users, ensuring they do a fair usage of the network resources.
In order to do so, it requires users to pay for the so-called RLN membership, which entitles the holder to send a given
amount of messages per unit of time while its active.
However at the time of writting, the collected fees from RLN memberships don't have a designated purpose.
In order to ensure the sustainability of the network and reward node operators for their work, one option would be
to distribute them among node operators.
We define node operators as entities that participate in the network, running nodes and relaying traffic. They are
the ones that make the network work. A node operator is also a registered entity known by the waku protocol,
see more information below.
This issue proposes how to distribute the generated rewards by RLN memberships to node operadors. It does so by
rewarding the node operators that vote on the correct Merkle root for each superepoch. The root agreed by a 2/3
supermajority is considered the corerct one, and the nodes that voted on that get a reward.
This reward is a fraction of the fees that were generated from membership registration during that superepoch.
Since gossipsub scoring punishes lazy peers and incentivices peers to behave properly, we assume that knowing the valid
Merkle root implies having participated in relay protocol, which is the behaviour we want to incentivice.
Proposal
This proposal introduces the following concepts:
-
- Node registration: Require node operators to register with a sybil-resistant mechanisim.
-
- Superepoch: Defining a
superepochthat matches the RLN membership renovation cycle.
- Superepoch: Defining a
-
- Messages Merkle Tree: A Merkle tree with all messages within a
superepoch.
- Messages Merkle Tree: A Merkle tree with all messages within a
-
- Commit-reveal: At the end of the
superepocheach operator can submit their local Merkle root of the Merkle tree containing all messages,
using a commit-reveal mechanisim to prevent lazy nodes from copying honest ones.
- Commit-reveal: At the end of the
-
- Claim: The Merkle root voted by the majority becomes the accepted root for that
superepoch, and every node is given/n
the rewards from the subscription fees of thatsuperepoch, wherenis the amount of nodes that matched the majority.
- Claim: The Merkle root voted by the majority becomes the accepted root for that
Below, each point is ellaborated.
1. Node registration
Since anyone would be able to submit a vote on the Merkle root, we need some kind of pseudo-identity to sybil-protect the voting.
Otherwise the same entity knowing a valid Merkle root, defined as the one that represent a Merkle tree constructed by all messages within a superepoch
could vote multiple times, getting more rewards than it should.
A suggested mechanisim is to require a STAKE_AMOUNT for node operators, which provides an economic sybil-protection.
When an operator stakes this amount, it becomes eligible to participate in the voting and hence, eligible for rewards.
When the operator no longer wants to participate, it will be returned.
The stake can be slashed if they dont vote in SUPEREPOCHS_PENALTY consecutive superepochs.
Its yet to be defined if there would be other slashing conditions.
2. Superepoch
A superepoch is the time window used for voting. During each superepoch nodes construct a Merkle tree with all seen messages
and once finished, the Merkle root is calculated.
The superepoch matches the "billing period", see comment.
In other words, if 10 users paid an RLN membership for a given superepoch then all this generated fees are distributes
among the nodes operators that participated in this superepoch.
3. Messages Merkle Tree
For each superepoch node operators construct a Merkle tree with all the messages they have:
- Seen in the network. With the help of gossipsub scoring, we assume that a node that is able to see messages in the network is because its also relaying them.
Otherwise its score would be penalized. - Got from store and store sync. We acknowledge that nodes may have some downtime, so its accepted that some of these messages will come from store and not relay.
A protection shall be added to discard "lazy nodes", meaning that they don't participate in relay but manage to get a valid Merkle root.
4. Commit-reveal
Since all onchain activity is public and anyone can see it, we propose a commit-reveal mechanisim to prevent lazy nodes
from sniffing the blockchain and copying the Merkle root of honest nodes.
Once the superepoch finishes, a window of COMMIT_WINDOW_SLOTS opens, during which all registered nodes can
submit their vote on which root they consider to be valid for that superepoch. What the node operators commits to (aka commitment)
is a secret, in this case the root. The commitment is hash(root + salt). That would be public but since getting the preimage
of that hash is not possible, an attacker won't be able to reveal in the next phase.
Once the COMMIT_WINDOW_SLOTS is due, no more votes are accepted for that superepoch and a REVEAL_WINDOW_SLOTS window is opened.
During this window node operators can reveal their secret. If the provided root during the reveal phase matches hash(root + salt), then their
vote would be accepted.
Finally, once REVEAL_WINDOW_SLOTS is due eligible node operators can claim their share of the reward. See next section.
5. Claim
After REVEAL_WINDOW_SLOTS the commit-reveal phase is done and votes are counted. An example:
node0..4(5) voted on rootroot1.node5..24(20) voted on rootroot2.node25(1) voted on rootroot3.note26..30(4) did not vote.
As explained before, node operators are registered beforehand in the contract a priori so the total amount of votes are known.
The previous votes can be written as [num_votes, root_n] or [5, root1], [20, root2], [1, root3], [4, NaN].
With the votes, a simple 2/3 consensus of a supermajority of 66% is used to decide which root to accept.
The weights would be:
root15/30 = 16%root220/30 = 66%root31/30 = 3%
This means that root2 is accepted onchain as the Merkle root of all the messages seen during the superepoch.
Nodes that voted for that root are eligible for rewards.
The amount to be distributed is calculated as the amount of memberships * price paid for each membership for each superepoch.
If 100 active memberships were active and each one paid 10 tokens/superepoch, then the amount to spit is: 100 * 10 = 1000 tokens.
Membership fees would be split among the nodes that voted the agreed root, aka root2 meaning, 1000/20 = 50 tokens for node5..24.
Note that a node operator that does not vote during SUPEREPOCHS_PENALTY can be slashed by anyone, as this information is accesible onchain
by anyone. The whistleblower will get WHISTEBLOWER_REWARD which is <=STAKE_REQUIREMENT and the node will no longer be part of the
active node operators.
In order to make it gas efficient, each node operators rewards can be claimed at any time.
For each superepoch the claimable amount keep accumulating, so that the operator can claim their rewards of multiple superepochs at once.
Consensus
An interesting side effect of this proposal is that it introduces an onchain consensus of the messages sent for each superepoch.
This would allow light clients (eg filter) to verify that a given message was indeed sent through the network, since the onchain root
can be used.
Open problems
This proposal has some open problems:
- Handle lazy nodes, defined as entities not participating in relay but somehow getting a valid Merkle root.
They should not be eligible for rewards. - Handle nodes registering multiple stakes. An operator running just one node could stake
STAKE_AMOUNTfor multiple node operators.
This will allow it to vote multiple times but its only doing the work of one node.