diff --git a/print.html b/print.html index 82c6d50..b3f1a11 100644 --- a/print.html +++ b/print.html @@ -150,31 +150,31 @@
This topic is a part of complete overview by Blagoj.
RLN is a construct based on zero-knowledge proofs that enables spam prevention mechanism for decentralized, anonymous environments. In anonymous environments, the identity of the entities is unknown.
-The anonymity property opens up the possibility for spam attack and sybil attack vectors for certain applications, which could seriously degrade the user experience and the overall functioning of the application. For example, imagine a chat application, where users are anonymous. Now, everyone can write unlimited number of spam messages, while we don't have ability to kick this member, because the spammer is anonymous.
+RLN is a zero-knowledge gadget that enables spam prevention for decentralized, anonymous environments.
+The anonymity property opens up the possibility for spam and Sybil attack vectors for certain applications, which could seriously degrade the user experience and the overall functioning of the application. For example, imagine a chat application where users are anonymous. Now, everyone can write an unlimited number of spam messages, but we don't have the ability to kick this member because the spammer is anonymous.
RLN helps us identify and "kick" the spammer.
-Moreover RLN can be useful not only to prevent a spam attacks, but in general, to limit users (in anonymous environments) in the number of actions (f.e. to vote or to make a bid).
+Moreover, RLN can be useful not only to prevent spam attacks but, in general, to limit users (in anonymous environments) in the number of actions (f.e. to vote or to make a bid).
The RLN construct’s functionality consists of three parts, which when integrated together provide spam and sybil attack protection. These parts should be integrated by the upstream applications which require anonymity and spam protection. The applications can be centralized or decentralized. For decentralized applications, each user maintains a separate storage and compute resources for the application. The three parts are:
+The RLN construct's functionality consists of three parts, which, when integrated together, provide spam and Sybil attack protection. These parts should be integrated by the upstream applications, which require anonymity and spam protection. The applications can be centralized or decentralized. For decentralized applications, each user maintains separate storage and compute resources for the application. The three parts are:
Before registering to the application the user needs to generate a secret key and derive an identity commitment from the secret key using the Poseidon hash function identityCommitment = posseidonHash(secretKey).
The user registers to the application by providing a form of stake and their identity commitment, which is derived from the secret key. The application maintains a Merkle tree data structure (in the latest iteration of the RLN construct we use the Incremental Merkle Tree algorithm), which stores the identity commitments of the registered users. Upon successful registration the user’s identity commitment is stored in a leaf of the Merkle tree and an index is given to them, representing their position in the tree.
+Before registering to the application, the user needs to generate a secret key and derive an identity commitment from the secret key using the Poseidon hash function identityCommitment = posseidonHash(secretKey).
The user registers to the application by providing a form of stake and their identity commitment, which is derived from the secret key. The application maintains a Merkle tree data structure (in the latest iteration of RLN, we use an Incremental Merkle Tree algorithm for gas efficiency, but the Merkle tree does not have to be on-chain), which stores the identity commitments of the registered users. Upon successful registration, the user's identity commitment is stored in a leaf of the Merkle tree, and an index is given to them, representing their position in the tree.
For each interaction that the user wants to make with the application, the user must generate a zero-knowledge proof which ensures the other participants (the verifiers) that they are a valid member of the application and their identity commitment is part of the membership Merkle tree.
-The interactions are app specific, such as voting for voting application and message sending for chat applications. The verifier is usually a server for centralized applications, or the other users for decentralized applications.
-So, as it's been said there is a problem with spam, therefore we introduced an "anti-spam rule". The rule is usually in the form of:
-Users must not make more than X interactions per epoch.
The epoch can be translated as time interval of Y units of time unit Z. For simplicity sake, let’s transform the rule into: Users must not send more than 1 message per second.
We can implement this using Shamir's Secret Sharing scheme (read more), which allows you to split a secret (f.e. to n parts) and recover it when any m of n parts (m <= n) are presented.
Thus, users have to split their secret_key into n parts and for every interaction they have to reveal the new part of the secret_key. So, in addition to proving the membership in the Merkle Tree, users have to prove that the revealed part is truly the part of their secret_key.
If they make more interactions than allowed per epoch their secret key can be fully reconstructed.
+For each interaction that the user wants to make with the application, the user must generate a zero-knowledge proof ensuring that their identity commitment is part of the membership Merkle tree.
+There are a number of use-cases for RLN, such as voting applications (1 vote per election), chat (one message per second), and rate-limiting cache access (CDN denial of service protection). The verifier can be a server for centralized applications or the other users for decentralized applications.
+The general anti-spam rule is usually in the form of:
+Users must not make more than X interactions per epoch.
The epoch can be translated as a time interval of Y units of time unit Z. For simplicity's sake, let's transform the rule into: `Users must not send more than one message per second.
We can implement this using Shamir's Secret Sharing scheme (read more), which allows you to split a secret (f.e. to n parts) and recover it when any m' of n parts ('m <= n) are presented.
Thus, users have to split their secret_key into n parts, and for every interaction, they have to reveal the new part of the secret_key. So, in addition to proving the membership in the Merkle Tree, users have to prove that the revealed part is truly the part of their secret_key.
If they make more interactions than allowed per epoch, their secret key can be fully reconstructed.
The final property of the RLN mechanism is that it allows for the users to be removed from the membership tree by anyone that knows their secret key. The membership tree contains the identity commitments of all registered users. User’s identity commitment is derived from their secret key, and the secret key of the user is only revealed in a spam event (except for the scenarios where the original users wants to remove themselves, which they can always do because they know their secret key). When an economic stake is present, the RLN mechanism can be implemented in a way that the spammer’s stake is sent to the first user that correctly reports the spammer by providing the reconstructed secret key of the spammer as a proof.
+The final property of the RLN mechanism is that it allows for the users to be removed from the membership tree by anyone that knows their secret key. The membership tree contains the identity commitments of all registered users. Users' identity commitment is derived from their secret key, and the secret key of the user is only revealed in a spam event (except for the scenarios where the original users want to remove themselves, which they can always do because they know their secret key). When an economic stake is present, the RLN mechanism can be implemented in a way that the spammer's stake is sent to the first user that correctly reports the spammer by providing the reconstructed secret key of the spammer as proof.
This section provides deep and technical RLN overview.
We'll discuss:
diff --git a/searchindex.js b/searchindex.js index 71e91f5..b662134 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Object.assign(window.search, {"doc_urls":["rln.html#rln","overview.html#overview","what_is_rln.html#what-is-rate-limiting-nullifier","what_is_rln.html#how-it-works","what_is_rln.html#user-registration","what_is_rln.html#user-interaction","what_is_rln.html#user-removal-slashing","under_the_hood.html#under-the-hood","protocol_spec.html#technical-side-of-rln","protocol_spec.html#user-registration","protocol_spec.html#signalling","protocol_spec.html#slashing","protocol_spec.html#some-important-notes","protocol_spec.html#diagram","circuits.html#circuits","circuits.html#merkle-tree-circuit","uses.html#uses","uses.html#zk-chat","how_to_use.html#how-to-use","theory.html#theory","sss.html#shamirs-secret-sharing-scheme","appendix.html#appendix","terminology.html#terminology","references.html#references"],"index":{"documentStore":{"docInfo":{"0":{"body":35,"breadcrumbs":2,"title":1},"1":{"body":19,"breadcrumbs":2,"title":1},"10":{"body":64,"breadcrumbs":6,"title":1},"11":{"body":12,"breadcrumbs":6,"title":1},"12":{"body":159,"breadcrumbs":7,"title":2},"13":{"body":107,"breadcrumbs":6,"title":1},"14":{"body":26,"breadcrumbs":5,"title":1},"15":{"body":156,"breadcrumbs":7,"title":3},"16":{"body":0,"breadcrumbs":3,"title":1},"17":{"body":2,"breadcrumbs":4,"title":2},"18":{"body":14,"breadcrumbs":2,"title":1},"19":{"body":12,"breadcrumbs":2,"title":1},"2":{"body":83,"breadcrumbs":5,"title":3},"20":{"body":239,"breadcrumbs":8,"title":4},"21":{"body":9,"breadcrumbs":2,"title":1},"22":{"body":203,"breadcrumbs":3,"title":1},"23":{"body":26,"breadcrumbs":4,"title":1},"3":{"body":43,"breadcrumbs":3,"title":1},"4":{"body":65,"breadcrumbs":4,"title":2},"5":{"body":134,"breadcrumbs":4,"title":2},"6":{"body":63,"breadcrumbs":5,"title":3},"7":{"body":15,"breadcrumbs":5,"title":2},"8":{"body":37,"breadcrumbs":8,"title":3},"9":{"body":124,"breadcrumbs":7,"title":2}},"docs":{"0":{"body":"RLN (Rate-Limiting Nullifier) is a zk-gadget/protocol that enables spam prevention mechanism for anonymous environments. RLN is part of ( PSE ) Privacy & Scaling Explorations , a multidisciplinary team supported by the Ethereum Foundation. PSE explores new use cases for zero-knowledge proofs and other cryptographic primitives. alt text","breadcrumbs":"RLN » RLN","id":"0","title":"RLN"},"1":{"body":"This section is a starting point for understanding the concepts of RLN . Here we'll discuss: Basic explanation of the RLN protocol RLN protocol under the hood RLN uses","breadcrumbs":"Overview » Overview","id":"1","title":"Overview"},"10":{"body":"Now that the user is registered, he wants to interact with the system. Imagine that the system is an anonymous chat and the interaction is the sending of messages. So, to send a message user have to come up with share - the point (x, y) on her polynomial. We denote: x = Poseidon(message), and y = A(x). Thus, if the same epoch user sends more than one message, their polynomial and, therefore, their secret (a_0) can be recovered. Of course, we somehow must prove that our share = (x, y) is valid (that this is really a point on our polynomial = A(x)), as well as we must prove other things are valid too, that's why we use zkSNARK. An explanation of the zk-circuits can be found in the next topic.","breadcrumbs":"Overview » Under the hood » Protocol spec » Signalling","id":"10","title":"Signalling"},"11":{"body":"As it's been said, if a user sends more than one message, everyone else will be able to recover his secret, slash him and take his stake.","breadcrumbs":"Overview » Under the hood » Protocol spec » Slashing","id":"11","title":"Slashing"},"12":{"body":"There are also nullifier and rln_identifier, which can be found in the RLN protocol/circuits. So, rln_identifier is just a random value that's unique per RLN app. It's used for additional cross-application security - to protect the user secrets from being compromised if they use the same credentials across different RLN apps. If rln_identifier is not present, the user uses the same credentials and sends a message in two different RLN apps using the same epoch, then their secret key can be revealed. Adding the rln_identifier field, we obscure the nullifier, so this kind of attack cannot happen. The only kind of attack that is possible is if we have an entity with a global view of all messages, and they try to brute-force different combinations of x and y shares for different nullifiers. Now, imagine there are a lot of users sending messages, and after each received message, we need to check if any member can be slashed. To do this, we can use all combinations of received shares and try to recover the polynomial, but this is a naive and non-optimal approach. Suppose we have a mechanism that will tell us about the connection between a person and their messages while not revealing their identity. In that case, we can solve this without brute-forcing all possibilities by using a public nullifier (nullifier = Poseidon(a_1, rln_identifier)), so if a user sends more than one message, it will be immediately visible to everyone. Also, in our example (and zk-chat implementation), we use linear polynomial, but SSS allows us to use various degree polynomials; therefore we can implement a protocol, where more than one signal (message) can be sent in per epoch. To learn more, check out the specification ; there are also circuits implemented for various degree polynomials too.","breadcrumbs":"Overview » Under the hood » Protocol spec » Some important notes","id":"12","title":"Some important notes"},"13":{"body":"flowchart TB subgraph Generate Secret Key random0(Random 32 bytes) --> a_0(Secret Key) random1(Random 32 bytes) --> a_0 end subgraph RLN subgraph Identity Commitment a_0 --> h0(Poseidon Hash) h0 --> q(Identity Commitment) end subgraph Calculate Internal Nullifier a_0 --> h1(Poseidon Hash) epoch(Epoch) --> h1 h1 --> a_1 rln_identifier(RLN Identifier) --> h2(Poseidon Hash) a_1 --> h2 h2 --> nullifier(RLN Internal Nullifier) end subgraph Merkle Tree q --> merkle_tree_inclusion_proof(Merkle Tree Inclusion Proof) merkle_tree_inclusion_proof --> root(ZKP of Merkle Tree Root) end subgraph Shamirs Secret Scheme a_0 --> plus(+) a_1 --> multiply(*) x(Hashed Messaage) --> multiply multiply --> plus plus --> share_y end nullifier --> proof(ZKP) root --> proof share_y --> proof end","breadcrumbs":"Overview » Under the hood » Protocol spec » Diagram","id":"13","title":"Diagram"},"14":{"body":"zkSNARK is used in the RLN core. Therefore, we need to represent the protocol in R1CS (as we use Groth16). Circom DSL was chosen for this. This section provides an explanation of RLN circuits. RLN circuits implement the logic described in previous topic .","breadcrumbs":"Overview » Under the hood » Circuits » Circuits","id":"14","title":"Circuits"},"15":{"body":"One of the key component of RLN is Incremental Merkle Tree . Let's look at the implementation . At the beginning of the file we denote that we use second version of Circom and include two helper zk-gadgets : pragma circom 2.0.0; include \"../node_modules/circomlib/circuits/poseidon.circom\";\ninclude \"../node_modules/circomlib/circuits/mux1.circom\"; Poseidon gadget is just the implementation of Poseidon hash function; mux1 gadget will be described later. Next, we can see two implemented gadgets: template PoseidonHashT3() { var nInputs = 2; signal input inputs[nInputs]; signal output out; component hasher = Poseidon(nInputs); for (var i = 0; i < nInputs; i ++) { hasher.inputs[i] <== inputs[i]; } out <== hasher.out;\n} template HashLeftRight() { signal input left; signal input right; signal output hash; component hasher = PoseidonHashT3(); left ==> hasher.inputs[0]; right ==> hasher.inputs[1]; hash <== hasher.out;\n} These are helper gadgets to make the code more clean. Poseidon gadget is implemented with the ability to take a different number of arguments. We use PoseidonHashT3() to initialize it like a function with two arguments. And HashLeftRight use PoseidonHashT3 in more \"readable\" way: it takes two inputs left and right and outputs the result of calculation. Next comes the core of Merkle Tree gadget: template MerkleTreeInclusionProof(n_levels) { signal input leaf; signal input path_index[n_levels]; signal input path_elements[n_levels][1]; signal output root; component hashers[n_levels]; component mux[n_levels]; signal levelHashes[n_levels + 1]; levelHashes[0] <== leaf; ... root <== levelHashes[n_levels];\n} Here we have three inputs: leaf, path_index and path_elements","breadcrumbs":"Overview » Under the hood » Circuits » Merkle Tree circuit","id":"15","title":"Merkle Tree circuit"},"16":{"body":"","breadcrumbs":"Overview » Uses » Uses","id":"16","title":"Uses"},"17":{"body":"https://github.com/njofce/zk-chat","breadcrumbs":"Overview » Uses » zk-chat","id":"17","title":"zk-chat"},"18":{"body":"This section provides information on how to use RLN in your project: JavaScript RLN (for rln-js ) Rust RLN (for zerokit-rln )","breadcrumbs":"How to use » How to use","id":"18","title":"How to use"},"19":{"body":"This section provides theoretical information that underpins RLN . Here we'll discuss: Shamir's Secret Sharing","breadcrumbs":"Theory » Theory","id":"19","title":"Theory"},"2":{"body":"This topic is a part of complete overview by Blagoj . RLN is a construct based on zero-knowledge proofs that enables spam prevention mechanism for decentralized, anonymous environments. In anonymous environments, the identity of the entities is unknown. The anonymity property opens up the possibility for spam attack and sybil attack vectors for certain applications, which could seriously degrade the user experience and the overall functioning of the application. For example, imagine a chat application, where users are anonymous. Now, everyone can write unlimited number of spam messages, while we don't have ability to kick this member, because the spammer is anonymous. RLN helps us identify and \"kick\" the spammer. Moreover RLN can be useful not only to prevent a spam attacks, but in general, to limit users (in anonymous environments) in the number of actions (f.e. to vote or to make a bid).","breadcrumbs":"Overview » What is RLN » What is Rate-Limiting Nullifier?","id":"2","title":"What is Rate-Limiting Nullifier?"},"20":{"body":"Shamirs Secret Sharing allows to split the secret to n parts and restore it upon presentation any m parts (m <= n) Sharmir's Secret Sharing wikipedia is a good reference to understand the concept. Reconstruction 1: https://github.com/akinovak/semaphore-lib/blob/5b9bb3210192c8e508eced7ef6579fd56e635ed0/src/rln.ts#L31 retrievePrivateKey(x1: bigint, x2:bigint, y1:bigint, y2:bigint): Buffer | ArrayBuffer { const slope = Fq.div(Fq.sub(y2, y1), Fq.sub(x2, x1)) const privateKey = Fq.sub(y1, Fq.mul(slope, x1)); return bigintConversion.bigintToBuf(Fq.normalize(privateKey)); } Reconstruction 2: https://github.com/akinovak/semaphore-lib/blob/rln_signature_changes/test/index.ts#L250 async function testRlnSlashingSimulation() { RLN.setHasher('poseidon'); const identity = RLN.genIdentity(); const privateKey = identity.keypair.privKey; const leafIndex = 3; const idCommitments: ArrayThis topic is a part of complete overview by Blagoj.
RLN is a construct based on zero-knowledge proofs that enables spam prevention mechanism for decentralized, anonymous environments. In anonymous environments, the identity of the entities is unknown.
-The anonymity property opens up the possibility for spam attack and sybil attack vectors for certain applications, which could seriously degrade the user experience and the overall functioning of the application. For example, imagine a chat application, where users are anonymous. Now, everyone can write unlimited number of spam messages, while we don't have ability to kick this member, because the spammer is anonymous.
+RLN is a zero-knowledge gadget that enables spam prevention for decentralized, anonymous environments.
+The anonymity property opens up the possibility for spam and Sybil attack vectors for certain applications, which could seriously degrade the user experience and the overall functioning of the application. For example, imagine a chat application where users are anonymous. Now, everyone can write an unlimited number of spam messages, but we don't have the ability to kick this member because the spammer is anonymous.
RLN helps us identify and "kick" the spammer.
-Moreover RLN can be useful not only to prevent a spam attacks, but in general, to limit users (in anonymous environments) in the number of actions (f.e. to vote or to make a bid).
+Moreover, RLN can be useful not only to prevent spam attacks but, in general, to limit users (in anonymous environments) in the number of actions (f.e. to vote or to make a bid).
The RLN construct’s functionality consists of three parts, which when integrated together provide spam and sybil attack protection. These parts should be integrated by the upstream applications which require anonymity and spam protection. The applications can be centralized or decentralized. For decentralized applications, each user maintains a separate storage and compute resources for the application. The three parts are:
+The RLN construct's functionality consists of three parts, which, when integrated together, provide spam and Sybil attack protection. These parts should be integrated by the upstream applications, which require anonymity and spam protection. The applications can be centralized or decentralized. For decentralized applications, each user maintains separate storage and compute resources for the application. The three parts are:
Before registering to the application the user needs to generate a secret key and derive an identity commitment from the secret key using the Poseidon hash function identityCommitment = posseidonHash(secretKey).
The user registers to the application by providing a form of stake and their identity commitment, which is derived from the secret key. The application maintains a Merkle tree data structure (in the latest iteration of the RLN construct we use the Incremental Merkle Tree algorithm), which stores the identity commitments of the registered users. Upon successful registration the user’s identity commitment is stored in a leaf of the Merkle tree and an index is given to them, representing their position in the tree.
+Before registering to the application, the user needs to generate a secret key and derive an identity commitment from the secret key using the Poseidon hash function identityCommitment = posseidonHash(secretKey).
The user registers to the application by providing a form of stake and their identity commitment, which is derived from the secret key. The application maintains a Merkle tree data structure (in the latest iteration of RLN, we use an Incremental Merkle Tree algorithm for gas efficiency, but the Merkle tree does not have to be on-chain), which stores the identity commitments of the registered users. Upon successful registration, the user's identity commitment is stored in a leaf of the Merkle tree, and an index is given to them, representing their position in the tree.
For each interaction that the user wants to make with the application, the user must generate a zero-knowledge proof which ensures the other participants (the verifiers) that they are a valid member of the application and their identity commitment is part of the membership Merkle tree.
-The interactions are app specific, such as voting for voting application and message sending for chat applications. The verifier is usually a server for centralized applications, or the other users for decentralized applications.
-So, as it's been said there is a problem with spam, therefore we introduced an "anti-spam rule". The rule is usually in the form of:
-Users must not make more than X interactions per epoch.
The epoch can be translated as time interval of Y units of time unit Z. For simplicity sake, let’s transform the rule into: Users must not send more than 1 message per second.
We can implement this using Shamir's Secret Sharing scheme (read more), which allows you to split a secret (f.e. to n parts) and recover it when any m of n parts (m <= n) are presented.
Thus, users have to split their secret_key into n parts and for every interaction they have to reveal the new part of the secret_key. So, in addition to proving the membership in the Merkle Tree, users have to prove that the revealed part is truly the part of their secret_key.
If they make more interactions than allowed per epoch their secret key can be fully reconstructed.
+For each interaction that the user wants to make with the application, the user must generate a zero-knowledge proof ensuring that their identity commitment is part of the membership Merkle tree.
+There are a number of use-cases for RLN, such as voting applications (1 vote per election), chat (one message per second), and rate-limiting cache access (CDN denial of service protection). The verifier can be a server for centralized applications or the other users for decentralized applications.
+The general anti-spam rule is usually in the form of:
+Users must not make more than X interactions per epoch.
The epoch can be translated as a time interval of Y units of time unit Z. For simplicity's sake, let's transform the rule into: `Users must not send more than one message per second.
We can implement this using Shamir's Secret Sharing scheme (read more), which allows you to split a secret (f.e. to n parts) and recover it when any m' of n parts ('m <= n) are presented.
Thus, users have to split their secret_key into n parts, and for every interaction, they have to reveal the new part of the secret_key. So, in addition to proving the membership in the Merkle Tree, users have to prove that the revealed part is truly the part of their secret_key.
If they make more interactions than allowed per epoch, their secret key can be fully reconstructed.
The final property of the RLN mechanism is that it allows for the users to be removed from the membership tree by anyone that knows their secret key. The membership tree contains the identity commitments of all registered users. User’s identity commitment is derived from their secret key, and the secret key of the user is only revealed in a spam event (except for the scenarios where the original users wants to remove themselves, which they can always do because they know their secret key). When an economic stake is present, the RLN mechanism can be implemented in a way that the spammer’s stake is sent to the first user that correctly reports the spammer by providing the reconstructed secret key of the spammer as a proof.
+The final property of the RLN mechanism is that it allows for the users to be removed from the membership tree by anyone that knows their secret key. The membership tree contains the identity commitments of all registered users. Users' identity commitment is derived from their secret key, and the secret key of the user is only revealed in a spam event (except for the scenarios where the original users want to remove themselves, which they can always do because they know their secret key). When an economic stake is present, the RLN mechanism can be implemented in a way that the spammer's stake is sent to the first user that correctly reports the spammer by providing the reconstructed secret key of the spammer as proof.