This commit is contained in:
curryrasul
2023-07-06 18:22:32 +00:00
parent 9300728e0e
commit 296f75afa3
16 changed files with 818 additions and 370 deletions

View File

@@ -86,7 +86,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>

View File

@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html" class="active"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html" class="active"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -173,187 +173,135 @@
<li><a href="#utils-templates">Utils</a>
<ul>
<li><a href="#merkletreeinclusionproof">MerkleTreeInclusionProof</a></li>
<li><a href="#isininterval">IsInInterval</a></li>
<li><a href="#rangecheck">RangeCheck</a></li>
</ul>
</li>
<li><a href="#rln-same-templates">RLN-same</a></li>
<li><a href="#rln-diff-templates">RLN-diff</a></li>
<li><a href="#rln">RLN</a></li>
<li><a href="#withdrawal">Withdrawal</a></li>
</ul>
<hr />
<h2 id="utils"><a class="header" href="#utils">Utils</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/utils.circom">utils.circom</a> is a set of templates/gadgets that the RLN circuits uses.</p>
<p><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/main/circuits/utils.circom">utils.circom</a> is a set of templates/gadgets that the RLN circuit uses.</p>
<p>These are: </p>
<ul>
<li>MerkleTreeInclusionProof - Merkle Tree inclusion check, used like set membership check;</li>
<li>IsInInterval - used for range check.</li>
<li>MerkleTreeInclusionProof - Merkle tree inclusion check, used like set membership check;</li>
<li>RangeCheck - used for range check.</li>
</ul>
<p>Their description is given below.</p>
<h3 id="merkletreeinclusionproof"><a class="header" href="#merkletreeinclusionproof">MerkleTreeInclusionProof</a></h3>
<p><code>MerkleTreeInclusionProof(DEPTH)</code> template used for verification of inclusion in full binary incremental merkle tree. The implementation is a fork of https://github.com/privacy-scaling-explorations/incrementalquintree, and changed to <em>binary</em> tree and refactored to <em>Circom 2.1.0</em>.</p>
<p><strong>MerkleTreeInclusionProof(DEPTH)</strong> template used for verification of inclusion in full binary incremental merkle tree. The implementation is a fork of https://github.com/privacy-scaling-explorations/incrementalquintree, and changed to <em>binary</em> tree and refactored to <em>Circom 2.1.0</em>.</p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>DEPTH</code> - depth of the Merkle Tree.</li>
<li><strong>DEPTH</strong> - depth of the Merkle Tree.</li>
</ul>
<p><strong>Inputs</strong>:</p>
<ul>
<li><code>leaf</code> - <code>Poseidon(elem)</code>, where <code>elem</code> is the element that's checked for inclusion;</li>
<li><code>pathIndex[DEPTH]</code> - array of length = <code>DEPTH</code>, consists of <code>0 | 1</code>, represents Merkle proof path.
Basically, it says how to calculate Poseidon hash, e.g. for two inputs <code>input1</code>, <code>input2</code>, if the <code>pathIndex[i] = 0</code> it shoud be calculated as <code>Poseidon(input1, input2)</code>, otherwise <code>Poseidon(input2, input1)</code>;</li>
<li><code>pathElements[DEPTH]</code> - array of length = <code>DEPTH</code>, represents elements of the Merkle proof.</li>
<li>\(leaf\) - \(Poseidon(elem)\), where \(elem\) is the element that's checked for inclusion;</li>
<li>\(pathIndex[DEPTH]\) - array of length = \(DEPTH\), consists of \(0 | 1\), represents Merkle proof path.
Basically, it says how to calculate Poseidon hash, e.g. for two inputs \(input1\), \(input2\), if the \(pathIndex[i] = 0\) it shoud be calculated as \(Poseidon(input1, input2)\), otherwise \(Poseidon(input2, input1)\);</li>
<li>\(pathElements[DEPTH]\) - array of length = \(DEPTH\), represents elements of the Merkle proof.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>root</code> - Root of the merkle tree.</li>
<li>\(root\) - Root of the merkle tree.</li>
</ul>
<p><strong>Templates used</strong>:</p>
<ul>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/mux1.circom">mux1.circom</a> from circomlib;</li>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom">poseidon.circom</a> from circomlib.</li>
</ul>
<h3 id="isininterval"><a class="header" href="#isininterval">IsInInterval</a></h3>
<p><code>IsInInterval(LIMIT_BIT_SIZE)</code> template used for range check, e.g. (x &lt;= y &lt;= z).</p>
<h3 id="rangecheck"><a class="header" href="#rangecheck">RangeCheck</a></h3>
<p><strong>RangeCheck(LIMIT_BIT_SIZE)</strong> template used for range check, e.g. \(x \le y \le z\).</p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>LIMIT_BIT_SIZE</code> - maximum bit size of numbers that are used in range check, f.e. for the <code>LIMIT_BIT_SIZE</code> = 16, input numbers allowed to be in the interval <code>[0, 65536)</code>.</li>
<li>\(LIMIT\_BIT\_SIZE\) - maximum bit size of numbers that are used in range check, f.e. for the \(LIMIT\_BIT\_SIZE = 16\), input numbers allowed to be in the interval \([0, 65536)\).</li>
</ul>
<p><strong>Inputs</strong>:</p>
<ul>
<li><code>in[3]</code> - array of 3 elements.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>out</code> - bool value (<code>0 | 1</code>). Outputs 1 when the circuit is satisfied, otherwise - 0.</li>
<li>\(messageId\) - denotes counter value, that'll be described further;</li>
<li>\(limit\) - maximum value.</li>
</ul>
<p><strong>Templates used</strong>:</p>
<ul>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/comparators.circom#L105"><code>LessEqThan(n)</code></a> from circomlib.</li>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/comparators.circom#L105">LessThan(n)</a> from circomlib;</li>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/bitify.circom#L25">Num2Bits(n)</a> from circomlib.</li>
</ul>
<p><strong>Logic/Constraints</strong>:
Checked that <code>in[0] &lt;= in[1] &lt;= in[2]</code>. That's done by combining two <code>LessEqThan</code> checks.
<code>out</code> value is calculated as a multiplication of two <code>LessEqThan</code> outputs.</p>
Checked that \(0 \le messageId &lt; limit\). </p>
<hr />
<h2 id="rln-same"><a class="header" href="#rln-same">RLN-same</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/rln-same.circom">rln-same.circom</a> is a template that's used for <a href="https://rfc.vac.dev/spec/58/#rln-same-flow">RLN-same protocol</a>. </p>
<h2 id="rln"><a class="header" href="#rln">RLN</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/main/circuits/rln.circom">rln.circom</a> is a template that's used for RLN protocol. </p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>DEPTH</code> - depth of a Merkle Tree. Described <a href="#merkletreeinclusionproof">here</a>;</li>
<li><code>LIMIT_BIT_SIZE</code> - maximum bit size of numbers that are used in range check. Described <a href="#isininterval">here</a>.</li>
<li>\(DEPTH\) - depth of a Merkle Tree. Described <a href="#merkletreeinclusionproof">here</a>;</li>
<li>\(LIMIT\_BIT\_SIZE\) - maximum bit size of numbers that are used in range check. Described <a href="#rangecheck">here</a>.</li>
</ul>
<p><strong>Private inputs</strong>:</p>
<ul>
<li><code>identitySecret</code> - randomly generated number in <code>F_p</code>, used as private key;</li>
<li><code>messageId</code> - id of the message;</li>
<li><code>pathElements[DEPTH]</code> - pathElements[DEPTH], described <a href="#merkletreeinclusionproof">here</a>;</li>
<li><code>identityPathIndex[DEPTH]</code> - pathIndex[DEPTH], described <a href="#merkletreeinclusionproof">here</a>.</li>
<li>\(identitySecret\) - randomly generated number in \(\mathbb{F_p}\), used as a private key;</li>
<li>\(userMessageLimit\) - message limit of the user;</li>
<li>\(messageId\) - id of the message;</li>
<li>\(pathElements[DEPTH]\) - pathElements[DEPTH], described <a href="#merkletreeinclusionproof">here</a>;</li>
<li>\(identityPathIndex[DEPTH]\) - pathIndex[DEPTH], described <a href="#merkletreeinclusionproof">here</a>.</li>
</ul>
<p><strong>Public inputs</strong>:</p>
<ul>
<li><code>x</code> - <code>Hash(signal)</code>, where <code>signal</code> is for example message, that was sent by user;</li>
<li><code>externalNullifier</code> - <code>Hash(epoch, rln_identifier)</code>;</li>
<li><code>messageLimit</code> - message limit of an RLN app.</li>
<li>\(x\) - \(Hash(signal)\), where \(signal\) is for example message, that was sent by user;</li>
<li>\(externalNullifier\) - \(Hash(epoch, rln_identifier)\).</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>y</code> - calculated first-degree linear polynomial (y = kx + b);</li>
<li><code>root</code> - root of the Merkle Tree;</li>
<li><code>nullifier</code> - internal nullifier/pseudonym of the user in anonyomus environment.</li>
<li>\(y\) - calculated first-degree linear polynomial \((y = kx + b)\);</li>
<li>\(root\) - root of the Merkle Tree;</li>
<li>\(nullifier\) - internal nullifier/pseudonym of the user in anonyomus environment.</li>
</ul>
<p><strong>Logic/Constraints</strong>:</p>
<ol>
<li>Merkle tree membership check:
<ul>
<li><code>identityCommitment</code> = <code>Poseidon(identitySecret)</code> calculation;</li>
<li><a href="#merkletreeinclusionproof">Merkle tree inclusion check</a> for the <code>identityCommitment</code>.</li>
<li>\(identityCommitment = Poseidon(identitySecret)\) calculation;</li>
<li>\(rateCommitment = Poseidon(identityCommitment, userMessageLimit)\) calculation;</li>
<li><a href="#merkletreeinclusionproof">Merkle tree inclusion check</a> for the \(rateCommitment\).</li>
</ul>
</li>
<li>Range check:
<ul>
<li><a href="#isininterval">Range check</a> that <code>1 &lt;= messageId &lt;= messageLimit</code>.</li>
<li><a href="#rangecheck">Range check</a> that \(0 \le messageId &lt; limit\).</li>
</ul>
</li>
<li>Polynomial share calculation:
<ul>
<li><code>a1</code> = <code>Poseidon(identitySecret, externalNullifier, messageId)</code>;</li>
<li><code>y</code> = <code>identitySecret + a1 * x</code>.</li>
<li>\(a_1 = Poseidon(identitySecret, externalNullifier, messageId)\);</li>
<li>\(y = identitySecret + a_1 * x\).</li>
</ul>
</li>
<li>Output of calculated <code>root</code>, <code>share</code> and <code>nullifier</code> = <code>Poseidon(a_1)</code> values.</li>
</ol>
<hr />
<h2 id="rln-diff"><a class="header" href="#rln-diff">RLN-diff</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/rln-diff.circom">rln-diff.circom</a> is a template that's used for <a href="https://rfc.vac.dev/spec/58/#rln-diff-flow">RLN-diff protocol</a>. </p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>DEPTH</code> - depth of a Merkle Tree. Described <a href="#merkletreeinclusionproof">here</a>;</li>
<li><code>LIMIT_BIT_SIZE</code> - maximum bit size of numbers that are used in range check. Described <a href="#isininterval">here</a>.</li>
</ul>
<p><strong>Private inputs</strong>:</p>
<ul>
<li><code>identitySecret</code> - randomly generated number in <code>F_p</code>, used as a private key;</li>
<li><code>userMessageLimit</code> - message limit of the user;</li>
<li><code>messageId</code> - id of the message;</li>
<li><code>pathElements[DEPTH]</code> - pathElements[DEPTH], described <a href="#merkletreeinclusionproof">here</a>;</li>
<li><code>identityPathIndex[DEPTH]</code> - pathIndex[DEPTH], described <a href="#merkletreeinclusionproof">here</a>.</li>
</ul>
<p><strong>Public inputs</strong>:</p>
<ul>
<li><code>x</code> - <code>Hash(signal)</code>, where <code>signal</code> is for example message, that was sent by user;</li>
<li><code>externalNullifier</code> - <code>Hash(epoch, rln_identifier)</code>.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>y</code> - calculated first-degree linear polynomial (y = kx + b);</li>
<li><code>root</code> - root of the Merkle Tree;</li>
<li><code>nullifier</code> - internal nullifier/pseudonym of the user in anonyomus environment.</li>
</ul>
<p><strong>Logic/Constraints</strong>:</p>
<ol>
<li>Merkle tree membership check:
<ul>
<li><code>identityCommitment</code> = <code>Poseidon(identitySecret, )</code> calculation;</li>
<li><code>rateCommitment</code> = <code>Poseidon(identityCommitment, userMessageLimit)</code> calculation;</li>
<li><a href="#merkletreeinclusionproof">Merkle tree inclusion check</a> for the <code>rateCommitment</code>.</li>
</ul>
</li>
<li>Range check:
<ul>
<li><a href="#isininterval">Range check</a> that <code>1 &lt;= messageId &lt;= userMessageLimit</code>.</li>
</ul>
</li>
<li>Polynomial share calculation:
<ul>
<li><code>a1</code> = <code>Poseidon(identitySecret, externalNullifier, messageId)</code>;</li>
<li><code>y</code> = <code>identitySecret + a1 * x</code>.</li>
</ul>
</li>
<li>Output of calculated <code>root</code>, <code>share</code> and <code>nullifier</code> = <code>Poseidon(a_1)</code> values.</li>
<li>Output of calculated \(root\), \(y = share\) and \(nullifier = Poseidon(a_1)\) values.</li>
</ol>
<hr />
<h3 id="withdrawal"><a class="header" href="#withdrawal">Withdrawal</a></h3>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/withdraw.circom">withdraw.circom</a> is a template that's used for the withdrawal/slashing and is needed to prevent front run while withdrawing the stake from the smart-contract/registry. </p>
<p><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/main/circuits/withdraw.circom">withdraw.circom</a> is a circuit that's used for the withdrawal/slashing and is needed to prevent frontrun while withdrawing the stake from the smart-contract/registry. </p>
<p><strong>Private inputs</strong>:</p>
<ul>
<li><code>identitySecret</code> - randomly generated number in <code>F_p</code>, used as private key.</li>
<li>\(identitySecret\) - randomly generated number in \(\mathbb{F_p}\), used as private key.</li>
</ul>
<p><strong>Public inputs</strong>:</p>
<ul>
<li><code>addressHash</code> - <code>F_p</code> scalar field element. <code>addressHash</code> = <code>Hash(address)</code>, where <code>address</code> is ETH address that'll receive stake. </li>
<li>\(address\) - \(\mathbb{F_p}\) scalar field element; denotes ETH address that'll receive stake. </li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>identityCommitment</code> = <code>Poseidon(identitySecret)</code>.</li>
<li>\(identityCommitment = Poseidon(identitySecret)\).</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="protocol_spec_v2.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="protocol_spec.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="uses.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next" href="smart_contract.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
@@ -363,11 +311,11 @@ Checked that <code>in[0] &lt;= in[1] &lt;= in[2]</code>. That's done by combinin
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="protocol_spec_v2.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="protocol_spec.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="uses.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next" href="smart_contract.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>

View File

@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html" class="active"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html" class="active"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>

View File

@@ -3,7 +3,7 @@
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Protocol spec V2 - Rate-Limiting Nullifier</title>
<title>KZG-RLN - Rate-Limiting Nullifier</title>
<!-- Custom HTML head -->
@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html" class="active"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html" class="active"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -168,82 +168,17 @@
<div id="content" class="content">
<main>
<h1 id="protocol-spec-v2"><a class="header" href="#protocol-spec-v2">Protocol spec V2</a></h1>
<h2 id="tldr"><a class="header" href="#tldr">TL;DR</a></h2>
<p>The main goal of RLN v2 circuits is to make it possible to have a custom amount of messages (signals) per epoch without using a separate circuit or high-degree polynomials for <a href="https://rate-limiting-nullifier.github.io/rln-docs/sss.html">Shamir's Secret Sharing</a>.</p>
<h2 id="rln-v1"><a class="header" href="#rln-v1">RLN V1</a></h2>
<p>The <a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits/blob/master/circuits/rln.circom">Current RLN circuit</a> uses a first-degree polynomial for shares generation (and slashing). Therefore, there is a limit - one message per epoch. </p>
<p>There have been attempts to make schemes in which the message limit per epoch is greater than one. For example, <a href="https://hackmd.io/zOk-bQ2GSgaJ1t1bI7zrWQ?view">N-RLN scheme</a> &amp; <a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits/blob/master/circuits/nrln-base.circom">N-RLN Circuits</a>. But this approach is very problematic; the bigger the epoch limit, the higher the polynomial for Shamir's Secret Sharing, and the more complicated the circuit is(more R1CS, etc.).</p>
<p>We have generally advised using 1 message/signal per epoch and adjusting the epoch length to match the rate limit desired for your use case. However, this isnt very flexible and constrains the epoch length for all users to be the same per semaphore group (merkle tree).</p>
<h3 id="overview-of-rln-v1-circuits"><a class="header" href="#overview-of-rln-v1-circuits">Overview of RLN v1 circuits</a></h3>
<p>Before we move on, this is a quick refresher on the inputs/outputs of the RLN v1 circuits and their general purpose. If you want more detail on how RLN circuits work, please <a href="https://rate-limiting-nullifier.github.io/rln-docs/protocol_spec.html">read this</a>, which goes into more detail.</p>
<p><strong>Inputs</strong>:</p>
<p>Public: </p>
<ul>
<li><code>external_nullifier</code> = <code>h(rln_identifier, epoch)</code> - <em>This identifies a unique epoch per app</em>, where <code>rln_identifier</code> is some unique identifier for an app and <code>epoch</code> is some unique identifier for an event or time;</li>
<li><code>x</code> = <code>h(message)</code>.</li>
</ul>
<p>Private: </p>
<ul>
<li>Secret Key <code>h(trapdoor, nullifier)</code> - This is to prove you are in some merkle tree, and to make the <code>y_share</code>, and <code>internal_nullifier</code> unique to an <code>id_commitment</code>.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>Internal_Nullifier</code>
<ul>
<li>Used to identify a unique user during a specific epoch (external_nullifier)</li>
</ul>
</li>
<li><code>Y_Share</code>
<ul>
<li>This is the <a href="https://rate-limiting-nullifier.github.io/rln-docs/sss.html">Shamir's Secret Sharing</a> share</li>
</ul>
</li>
</ul>
<h2 id="update-to-v2"><a class="header" href="#update-to-v2">Update to V2</a></h2>
<p>Instead of using higher degree polynomials to generate coefficients for higher epoch limits, we can add an input to the hash function, which is a counter <code>k</code> that ranges from 1 to <code>n</code>, the <code>epoch limit</code> (which can be <code>id_commitment</code> specific, for example in a registry contract.</p>
<p>The scheme would work as follows:</p>
<ul>
<li>The user generates a secret <code>a_0</code></li>
<li>The coefficient <code>a_1</code> is generated by taking the hash of <code>a_0</code>, an external nullifier, and the counter <code>k</code>: h(<code>a_0</code>, <code>external_nullifier</code>, <code>k</code>)</li>
<li>The <code>internal_nullifier</code> is then generated by taking the hash of <code>a_1</code>: h(<code>a_1</code>)</li>
</ul>
<p>By adding the counter <code>k</code> as an input to the hash function, the scheme becomes more flexible but still simple. It ensures that the user cannot use a value of <code>k</code> greater than <code>n</code>, which is the epoch limit, and if the user uses the same value of <code>k</code> twice, they will have two or more <code>internal_nullifiers</code> that collide, which allow the <code>y_shares</code> to be used determine their slashing credentials.</p>
<p>Overall, this proposal aims to provide more flexibility to the scheme while maintaining its simplicity.</p>
<h3 id="additional-inputs"><a class="header" href="#additional-inputs">Additional Inputs</a></h3>
<p>The only additional inputs are:</p>
<ul>
<li>[private] Message ID (Counter) <code>k</code> - a unique id per message per epoch, somewhere between the range <code>1 &lt; k &lt; n</code></li>
<li>[public] Message Limit <code>n</code> - the max number of messages a user can send</li>
</ul>
<h3 id="additional-properties"><a class="header" href="#additional-properties">Additional Properties</a></h3>
<p>There are also other cool features that come along with using this scheme:</p>
<ul>
<li>Internal nullifier value is different for different messages during the epoch (so it's more anonymous), even when having more than 1 signal per epoch</li>
<li>It's more secure and resistant to algebraic attacks (which could arise in the N-RLN scheme linked above)</li>
</ul>
<h3 id="different-rate-limits"><a class="header" href="#different-rate-limits">Different Rate-Limits</a></h3>
<p>By using this scheme we created a circuit, that will allow us to use different rate-limits for different users, for example based on their stake.</p>
<p>We can do that by committing to not only our secret, but our secret and limit:</p>
<ol>
<li>Registry (map) is stored on a smart-contract, where keys are public keys (<code>id_commitment = Hash(identity_secret)</code>) of users and values are some metadata (for example <code>limit</code> number or stake amount);</li>
<li>Merkle tree, where leaves are <code>rate_limit</code>'s = <code>Hash(id_commitment, userMessagelimit)</code> </li>
</ol>
<p>For example, the possible limit is 1000 (<code>n</code> = 1000), and each message costs 0.001 ETH (so you will have 1000 messages limit if you stake 1 ETH).</p>
<p>So, when you join app you attach the amount of stake you want and also send the <code>id_commitment</code> and <code>rate_commitment = Hash(id_commitment, userMessageLimit)</code> will be calculated on-chain based on your stake.</p>
<p>Signaling will use other circuit, where your <code>limit</code> is private input, and the counter <code>k</code> is checked that it's in the range from 1 to <code>userMessageLimit</code>.</p>
<hr />
<p><em>This text is from @AtHeartEngineer <a href="https://zkresear.ch/t/rate-limit-nullifier-v2-circuits/102">post</a> on <a href="https://zkresear.ch">zkResear.ch</a></em>.</p>
<h1 id="kzg-rln"><a class="header" href="#kzg-rln">KZG-RLN</a></h1>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="protocol_spec.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="research.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="formal_spec.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next" href="noir_rln.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
@@ -253,11 +188,11 @@
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="protocol_spec.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="research.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="formal_spec.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next" href="noir_rln.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>

219
noir_rln.html Normal file
View File

@@ -0,0 +1,219 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Noir-RLN - Rate-Limiting Nullifier</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- MathJax -->
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
</head>
<body>
<div id="body-container">
<!-- Provide site root to javascript -->
<script>
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var html = document.querySelector('html');
var sidebar = null;
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html" class="active"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<!-- Track and set sidebar scroll position -->
<script>
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
sidebarScrollbox.addEventListener('click', function(e) {
if (e.target.tagName === 'A') {
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
}
}, { passive: true });
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
sessionStorage.removeItem('sidebar-scroll');
if (sidebarScrollTop) {
// preserve sidebar scroll position when navigating via links within sidebar
sidebarScrollbox.scrollTop = sidebarScrollTop;
} else {
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
var activeSection = document.querySelector('#sidebar .active');
if (activeSection) {
activeSection.scrollIntoView({ block: 'center' });
}
}
</script>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Rate-Limiting Nullifier</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="noir-rln"><a class="header" href="#noir-rln">Noir-RLN</a></h1>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="kzg_rln.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="kzg_rln.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js"></script>
<script src="mark.min.js"></script>
<script src="searcher.js"></script>
<script src="clipboard.min.js"></script>
<script src="highlight.js"></script>
<script src="book.js"></script>
<!-- Custom JS scripts -->
<script src="mermaid.min.js"></script>
<script src="mermaid-init.js"></script>
</div>
</body>
</html>

View File

@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html" class="active"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html" class="active"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>

View File

@@ -86,7 +86,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -208,18 +208,20 @@
<h3 id="registration"><a class="header" href="#registration">Registration</a></h3>
<p>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: </p>
<p>\[identityCommitment = Poseidon(secretKey)\]</p>
<p>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 <strong>RLN</strong>, 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.</p>
<p>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 <strong>RLN</strong>, 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. Based on the stake amount apps can derive what's the messageLimit (\(userMessageLimit\)) for a user. Then the rateCommitment:</p>
<p>\[rateCommitment = Poseidon(identitytCommitment, userMessageLimit)\]</p>
<p>will be stored in the membership Merkle tree.</p>
<h3 id="interaction"><a class="header" href="#interaction">Interaction</a></h3>
<p>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.</p>
<p>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 (or specifically rate commitment) is the part of the membership Merkle tree.</p>
<p>There are a number of use-cases for <strong>RLN</strong>, 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.</p>
<p>The general anti-spam rule is usually in the form of:
<code>Users must not make more than X interactions per epoch.</code></p>
<p>The epoch can be translated as a time interval of <code>Y</code> units of time unit <code>Z</code>. For simplicity's sake, let's transform the rule into: `Users must not send more than one message per second.</p>
<p>We can implement this using <em>Shamir's Secret Sharing</em> scheme (<a href="./sss.html"><em>read more</em></a>), which allows you to split a secret (f.e. to <code>n</code> parts) and recover it when any <code>m</code> of <code>n</code> parts <code>(m &lt;= n)</code> are presented.</p>
<p>Thus, users have to split their <code>secret_key</code> into <code>n</code> parts, and for every interaction, they have to reveal the new part of the <code>secret_key.</code> So, in addition to proving the membership in the <em>Merkle Tree</em>, users have to prove that the revealed part is truly the part of their <code>secret_key.</code></p>
<p>The general anti-spam rule is usually in the form of: <em>users must not make more than X interactions per epoch</em>.</p>
<p>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: <em>users must not send more than one message per second</em>.</p>
<p>We can implement this using <a href="./sss.html"><em>Shamir's Secret Sharing (SSS)</em> scheme</a>, which allows you to split a secret to \(n\) parts and recover it when any \(m\) of \(n\) parts \(m \le n\) are presented.</p>
<p>Thus, users have to split their secret key into \(n\) parts, and for each interaction, they have to reveal the new part of the secret key. So, in addition to proving the membership, users have to prove that the revealed part is truly the part of their secret key.</p>
<p>If they make more interactions than allowed per epoch, their secret key can be fully reconstructed.</p>
<h3 id="withdrawal-or-slashing"><a class="header" href="#withdrawal-or-slashing">Withdrawal (or slashing)</a></h3>
<p>The final property of the <strong>RLN</strong> 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 <strong>RLN</strong> 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.</p>
<p>The final property of the <strong>RLN</strong> mechanism is that it allows for the users to be removed from the
membership tree by anyone that knows their secret key. Thus, if someone spams, it'll be possible to recover the secret key and withdraw the stake (or <em>slash</em>) of a spammer - that's why it's economically inefficient for users to spam.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="technical-side-of-rln"><a class="header" href="#technical-side-of-rln">Technical side of RLN</a></h1>
<p><em>This topic is a less strict version of specifications. If you want a more formal description, you can find specs in the <a href="./references.html">references</a>. Also, if you're unfamiliar with Shamir's Secret Sharing scheme, you can <a href="./sss.html">read it here</a>.</em></p>
<hr />
@@ -257,248 +259,131 @@ We denote: \(x = Poseidon(message), y = A(x)\). </p>
<h2 id="some-important-notes"><a class="header" href="#some-important-notes">Some important notes</a></h2>
<p>Also, in our example (and <a href="https://github.com/njofce/zk-chat">zk-chat</a> implementation), we use linear polynomial, but <a href="sss.html">SSS</a> 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. </p>
<p>To learn more, check out the <a href="https://hackmd.io/7GR5Vi28Rz2EpEmLK0E0Aw?view">specification</a>; there are also <a href="https://github.com/privacy-scaling-explorations/rln/tree/master/circuits">circuits</a> implemented for various degree polynomials too.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="protocol-spec-v2"><a class="header" href="#protocol-spec-v2">Protocol spec V2</a></h1>
<h2 id="tldr"><a class="header" href="#tldr">TL;DR</a></h2>
<p>The main goal of RLN v2 circuits is to make it possible to have a custom amount of messages (signals) per epoch without using a separate circuit or high-degree polynomials for <a href="https://rate-limiting-nullifier.github.io/rln-docs/sss.html">Shamir's Secret Sharing</a>.</p>
<h2 id="rln-v1"><a class="header" href="#rln-v1">RLN V1</a></h2>
<p>The <a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits/blob/master/circuits/rln.circom">Current RLN circuit</a> uses a first-degree polynomial for shares generation (and slashing). Therefore, there is a limit - one message per epoch. </p>
<p>There have been attempts to make schemes in which the message limit per epoch is greater than one. For example, <a href="https://hackmd.io/zOk-bQ2GSgaJ1t1bI7zrWQ?view">N-RLN scheme</a> &amp; <a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits/blob/master/circuits/nrln-base.circom">N-RLN Circuits</a>. But this approach is very problematic; the bigger the epoch limit, the higher the polynomial for Shamir's Secret Sharing, and the more complicated the circuit is(more R1CS, etc.).</p>
<p>We have generally advised using 1 message/signal per epoch and adjusting the epoch length to match the rate limit desired for your use case. However, this isnt very flexible and constrains the epoch length for all users to be the same per semaphore group (merkle tree).</p>
<h3 id="overview-of-rln-v1-circuits"><a class="header" href="#overview-of-rln-v1-circuits">Overview of RLN v1 circuits</a></h3>
<p>Before we move on, this is a quick refresher on the inputs/outputs of the RLN v1 circuits and their general purpose. If you want more detail on how RLN circuits work, please <a href="https://rate-limiting-nullifier.github.io/rln-docs/protocol_spec.html">read this</a>, which goes into more detail.</p>
<p><strong>Inputs</strong>:</p>
<p>Public: </p>
<ul>
<li><code>external_nullifier</code> = <code>h(rln_identifier, epoch)</code> - <em>This identifies a unique epoch per app</em>, where <code>rln_identifier</code> is some unique identifier for an app and <code>epoch</code> is some unique identifier for an event or time;</li>
<li><code>x</code> = <code>h(message)</code>.</li>
</ul>
<p>Private: </p>
<ul>
<li>Secret Key <code>h(trapdoor, nullifier)</code> - This is to prove you are in some merkle tree, and to make the <code>y_share</code>, and <code>internal_nullifier</code> unique to an <code>id_commitment</code>.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>Internal_Nullifier</code>
<ul>
<li>Used to identify a unique user during a specific epoch (external_nullifier)</li>
</ul>
</li>
<li><code>Y_Share</code>
<ul>
<li>This is the <a href="https://rate-limiting-nullifier.github.io/rln-docs/sss.html">Shamir's Secret Sharing</a> share</li>
</ul>
</li>
</ul>
<h2 id="update-to-v2"><a class="header" href="#update-to-v2">Update to V2</a></h2>
<p>Instead of using higher degree polynomials to generate coefficients for higher epoch limits, we can add an input to the hash function, which is a counter <code>k</code> that ranges from 1 to <code>n</code>, the <code>epoch limit</code> (which can be <code>id_commitment</code> specific, for example in a registry contract.</p>
<p>The scheme would work as follows:</p>
<ul>
<li>The user generates a secret <code>a_0</code></li>
<li>The coefficient <code>a_1</code> is generated by taking the hash of <code>a_0</code>, an external nullifier, and the counter <code>k</code>: h(<code>a_0</code>, <code>external_nullifier</code>, <code>k</code>)</li>
<li>The <code>internal_nullifier</code> is then generated by taking the hash of <code>a_1</code>: h(<code>a_1</code>)</li>
</ul>
<p>By adding the counter <code>k</code> as an input to the hash function, the scheme becomes more flexible but still simple. It ensures that the user cannot use a value of <code>k</code> greater than <code>n</code>, which is the epoch limit, and if the user uses the same value of <code>k</code> twice, they will have two or more <code>internal_nullifiers</code> that collide, which allow the <code>y_shares</code> to be used determine their slashing credentials.</p>
<p>Overall, this proposal aims to provide more flexibility to the scheme while maintaining its simplicity.</p>
<h3 id="additional-inputs"><a class="header" href="#additional-inputs">Additional Inputs</a></h3>
<p>The only additional inputs are:</p>
<ul>
<li>[private] Message ID (Counter) <code>k</code> - a unique id per message per epoch, somewhere between the range <code>1 &lt; k &lt; n</code></li>
<li>[public] Message Limit <code>n</code> - the max number of messages a user can send</li>
</ul>
<h3 id="additional-properties"><a class="header" href="#additional-properties">Additional Properties</a></h3>
<p>There are also other cool features that come along with using this scheme:</p>
<ul>
<li>Internal nullifier value is different for different messages during the epoch (so it's more anonymous), even when having more than 1 signal per epoch</li>
<li>It's more secure and resistant to algebraic attacks (which could arise in the N-RLN scheme linked above)</li>
</ul>
<h3 id="different-rate-limits"><a class="header" href="#different-rate-limits">Different Rate-Limits</a></h3>
<p>By using this scheme we created a circuit, that will allow us to use different rate-limits for different users, for example based on their stake.</p>
<p>We can do that by committing to not only our secret, but our secret and limit:</p>
<ol>
<li>Registry (map) is stored on a smart-contract, where keys are public keys (<code>id_commitment = Hash(identity_secret)</code>) of users and values are some metadata (for example <code>limit</code> number or stake amount);</li>
<li>Merkle tree, where leaves are <code>rate_limit</code>'s = <code>Hash(id_commitment, userMessagelimit)</code> </li>
</ol>
<p>For example, the possible limit is 1000 (<code>n</code> = 1000), and each message costs 0.001 ETH (so you will have 1000 messages limit if you stake 1 ETH).</p>
<p>So, when you join app you attach the amount of stake you want and also send the <code>id_commitment</code> and <code>rate_commitment = Hash(id_commitment, userMessageLimit)</code> will be calculated on-chain based on your stake.</p>
<p>Signaling will use other circuit, where your <code>limit</code> is private input, and the counter <code>k</code> is checked that it's in the range from 1 to <code>userMessageLimit</code>.</p>
<hr />
<p><em>This text is from @AtHeartEngineer <a href="https://zkresear.ch/t/rate-limit-nullifier-v2-circuits/102">post</a> on <a href="https://zkresear.ch">zkResear.ch</a></em>.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="formal-spec-of-circom-rln"><a class="header" href="#formal-spec-of-circom-rln">Formal spec of circom-rln</a></h1>
<ul>
<li><a href="formal_spec.html#utils-templates">Utils</a>
<ul>
<li><a href="formal_spec.html#merkletreeinclusionproof">MerkleTreeInclusionProof</a></li>
<li><a href="formal_spec.html#isininterval">IsInInterval</a></li>
<li><a href="formal_spec.html#rangecheck">RangeCheck</a></li>
</ul>
</li>
<li><a href="formal_spec.html#rln-same-templates">RLN-same</a></li>
<li><a href="formal_spec.html#rln-diff-templates">RLN-diff</a></li>
<li><a href="formal_spec.html#rln">RLN</a></li>
<li><a href="formal_spec.html#withdrawal">Withdrawal</a></li>
</ul>
<hr />
<h2 id="utils"><a class="header" href="#utils">Utils</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/utils.circom">utils.circom</a> is a set of templates/gadgets that the RLN circuits uses.</p>
<p><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/main/circuits/utils.circom">utils.circom</a> is a set of templates/gadgets that the RLN circuit uses.</p>
<p>These are: </p>
<ul>
<li>MerkleTreeInclusionProof - Merkle Tree inclusion check, used like set membership check;</li>
<li>IsInInterval - used for range check.</li>
<li>MerkleTreeInclusionProof - Merkle tree inclusion check, used like set membership check;</li>
<li>RangeCheck - used for range check.</li>
</ul>
<p>Their description is given below.</p>
<h3 id="merkletreeinclusionproof"><a class="header" href="#merkletreeinclusionproof">MerkleTreeInclusionProof</a></h3>
<p><code>MerkleTreeInclusionProof(DEPTH)</code> template used for verification of inclusion in full binary incremental merkle tree. The implementation is a fork of https://github.com/privacy-scaling-explorations/incrementalquintree, and changed to <em>binary</em> tree and refactored to <em>Circom 2.1.0</em>.</p>
<p><strong>MerkleTreeInclusionProof(DEPTH)</strong> template used for verification of inclusion in full binary incremental merkle tree. The implementation is a fork of https://github.com/privacy-scaling-explorations/incrementalquintree, and changed to <em>binary</em> tree and refactored to <em>Circom 2.1.0</em>.</p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>DEPTH</code> - depth of the Merkle Tree.</li>
<li><strong>DEPTH</strong> - depth of the Merkle Tree.</li>
</ul>
<p><strong>Inputs</strong>:</p>
<ul>
<li><code>leaf</code> - <code>Poseidon(elem)</code>, where <code>elem</code> is the element that's checked for inclusion;</li>
<li><code>pathIndex[DEPTH]</code> - array of length = <code>DEPTH</code>, consists of <code>0 | 1</code>, represents Merkle proof path.
Basically, it says how to calculate Poseidon hash, e.g. for two inputs <code>input1</code>, <code>input2</code>, if the <code>pathIndex[i] = 0</code> it shoud be calculated as <code>Poseidon(input1, input2)</code>, otherwise <code>Poseidon(input2, input1)</code>;</li>
<li><code>pathElements[DEPTH]</code> - array of length = <code>DEPTH</code>, represents elements of the Merkle proof.</li>
<li>\(leaf\) - \(Poseidon(elem)\), where \(elem\) is the element that's checked for inclusion;</li>
<li>\(pathIndex[DEPTH]\) - array of length = \(DEPTH\), consists of \(0 | 1\), represents Merkle proof path.
Basically, it says how to calculate Poseidon hash, e.g. for two inputs \(input1\), \(input2\), if the \(pathIndex[i] = 0\) it shoud be calculated as \(Poseidon(input1, input2)\), otherwise \(Poseidon(input2, input1)\);</li>
<li>\(pathElements[DEPTH]\) - array of length = \(DEPTH\), represents elements of the Merkle proof.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>root</code> - Root of the merkle tree.</li>
<li>\(root\) - Root of the merkle tree.</li>
</ul>
<p><strong>Templates used</strong>:</p>
<ul>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/mux1.circom">mux1.circom</a> from circomlib;</li>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom">poseidon.circom</a> from circomlib.</li>
</ul>
<h3 id="isininterval"><a class="header" href="#isininterval">IsInInterval</a></h3>
<p><code>IsInInterval(LIMIT_BIT_SIZE)</code> template used for range check, e.g. (x &lt;= y &lt;= z).</p>
<h3 id="rangecheck"><a class="header" href="#rangecheck">RangeCheck</a></h3>
<p><strong>RangeCheck(LIMIT_BIT_SIZE)</strong> template used for range check, e.g. \(x \le y \le z\).</p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>LIMIT_BIT_SIZE</code> - maximum bit size of numbers that are used in range check, f.e. for the <code>LIMIT_BIT_SIZE</code> = 16, input numbers allowed to be in the interval <code>[0, 65536)</code>.</li>
<li>\(LIMIT\_BIT\_SIZE\) - maximum bit size of numbers that are used in range check, f.e. for the \(LIMIT\_BIT\_SIZE = 16\), input numbers allowed to be in the interval \([0, 65536)\).</li>
</ul>
<p><strong>Inputs</strong>:</p>
<ul>
<li><code>in[3]</code> - array of 3 elements.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>out</code> - bool value (<code>0 | 1</code>). Outputs 1 when the circuit is satisfied, otherwise - 0.</li>
<li>\(messageId\) - denotes counter value, that'll be described further;</li>
<li>\(limit\) - maximum value.</li>
</ul>
<p><strong>Templates used</strong>:</p>
<ul>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/comparators.circom#L105"><code>LessEqThan(n)</code></a> from circomlib.</li>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/comparators.circom#L105">LessThan(n)</a> from circomlib;</li>
<li><a href="https://github.com/iden3/circomlib/blob/master/circuits/bitify.circom#L25">Num2Bits(n)</a> from circomlib.</li>
</ul>
<p><strong>Logic/Constraints</strong>:
Checked that <code>in[0] &lt;= in[1] &lt;= in[2]</code>. That's done by combining two <code>LessEqThan</code> checks.
<code>out</code> value is calculated as a multiplication of two <code>LessEqThan</code> outputs.</p>
Checked that \(0 \le messageId &lt; limit\). </p>
<hr />
<h2 id="rln-same"><a class="header" href="#rln-same">RLN-same</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/rln-same.circom">rln-same.circom</a> is a template that's used for <a href="https://rfc.vac.dev/spec/58/#rln-same-flow">RLN-same protocol</a>. </p>
<h2 id="rln"><a class="header" href="#rln">RLN</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/main/circuits/rln.circom">rln.circom</a> is a template that's used for RLN protocol. </p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>DEPTH</code> - depth of a Merkle Tree. Described <a href="formal_spec.html#merkletreeinclusionproof">here</a>;</li>
<li><code>LIMIT_BIT_SIZE</code> - maximum bit size of numbers that are used in range check. Described <a href="formal_spec.html#isininterval">here</a>.</li>
<li>\(DEPTH\) - depth of a Merkle Tree. Described <a href="formal_spec.html#merkletreeinclusionproof">here</a>;</li>
<li>\(LIMIT\_BIT\_SIZE\) - maximum bit size of numbers that are used in range check. Described <a href="formal_spec.html#rangecheck">here</a>.</li>
</ul>
<p><strong>Private inputs</strong>:</p>
<ul>
<li><code>identitySecret</code> - randomly generated number in <code>F_p</code>, used as private key;</li>
<li><code>messageId</code> - id of the message;</li>
<li><code>pathElements[DEPTH]</code> - pathElements[DEPTH], described <a href="formal_spec.html#merkletreeinclusionproof">here</a>;</li>
<li><code>identityPathIndex[DEPTH]</code> - pathIndex[DEPTH], described <a href="formal_spec.html#merkletreeinclusionproof">here</a>.</li>
<li>\(identitySecret\) - randomly generated number in \(\mathbb{F_p}\), used as a private key;</li>
<li>\(userMessageLimit\) - message limit of the user;</li>
<li>\(messageId\) - id of the message;</li>
<li>\(pathElements[DEPTH]\) - pathElements[DEPTH], described <a href="formal_spec.html#merkletreeinclusionproof">here</a>;</li>
<li>\(identityPathIndex[DEPTH]\) - pathIndex[DEPTH], described <a href="formal_spec.html#merkletreeinclusionproof">here</a>.</li>
</ul>
<p><strong>Public inputs</strong>:</p>
<ul>
<li><code>x</code> - <code>Hash(signal)</code>, where <code>signal</code> is for example message, that was sent by user;</li>
<li><code>externalNullifier</code> - <code>Hash(epoch, rln_identifier)</code>;</li>
<li><code>messageLimit</code> - message limit of an RLN app.</li>
<li>\(x\) - \(Hash(signal)\), where \(signal\) is for example message, that was sent by user;</li>
<li>\(externalNullifier\) - \(Hash(epoch, rln_identifier)\).</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>y</code> - calculated first-degree linear polynomial (y = kx + b);</li>
<li><code>root</code> - root of the Merkle Tree;</li>
<li><code>nullifier</code> - internal nullifier/pseudonym of the user in anonyomus environment.</li>
<li>\(y\) - calculated first-degree linear polynomial \((y = kx + b)\);</li>
<li>\(root\) - root of the Merkle Tree;</li>
<li>\(nullifier\) - internal nullifier/pseudonym of the user in anonyomus environment.</li>
</ul>
<p><strong>Logic/Constraints</strong>:</p>
<ol>
<li>Merkle tree membership check:
<ul>
<li><code>identityCommitment</code> = <code>Poseidon(identitySecret)</code> calculation;</li>
<li><a href="formal_spec.html#merkletreeinclusionproof">Merkle tree inclusion check</a> for the <code>identityCommitment</code>.</li>
<li>\(identityCommitment = Poseidon(identitySecret)\) calculation;</li>
<li>\(rateCommitment = Poseidon(identityCommitment, userMessageLimit)\) calculation;</li>
<li><a href="formal_spec.html#merkletreeinclusionproof">Merkle tree inclusion check</a> for the \(rateCommitment\).</li>
</ul>
</li>
<li>Range check:
<ul>
<li><a href="formal_spec.html#isininterval">Range check</a> that <code>1 &lt;= messageId &lt;= messageLimit</code>.</li>
<li><a href="formal_spec.html#rangecheck">Range check</a> that \(0 \le messageId &lt; limit\).</li>
</ul>
</li>
<li>Polynomial share calculation:
<ul>
<li><code>a1</code> = <code>Poseidon(identitySecret, externalNullifier, messageId)</code>;</li>
<li><code>y</code> = <code>identitySecret + a1 * x</code>.</li>
<li>\(a_1 = Poseidon(identitySecret, externalNullifier, messageId)\);</li>
<li>\(y = identitySecret + a_1 * x\).</li>
</ul>
</li>
<li>Output of calculated <code>root</code>, <code>share</code> and <code>nullifier</code> = <code>Poseidon(a_1)</code> values.</li>
</ol>
<hr />
<h2 id="rln-diff"><a class="header" href="#rln-diff">RLN-diff</a></h2>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/rln-diff.circom">rln-diff.circom</a> is a template that's used for <a href="https://rfc.vac.dev/spec/58/#rln-diff-flow">RLN-diff protocol</a>. </p>
<p><strong>Parameters</strong>:</p>
<ul>
<li><code>DEPTH</code> - depth of a Merkle Tree. Described <a href="formal_spec.html#merkletreeinclusionproof">here</a>;</li>
<li><code>LIMIT_BIT_SIZE</code> - maximum bit size of numbers that are used in range check. Described <a href="formal_spec.html#isininterval">here</a>.</li>
</ul>
<p><strong>Private inputs</strong>:</p>
<ul>
<li><code>identitySecret</code> - randomly generated number in <code>F_p</code>, used as a private key;</li>
<li><code>userMessageLimit</code> - message limit of the user;</li>
<li><code>messageId</code> - id of the message;</li>
<li><code>pathElements[DEPTH]</code> - pathElements[DEPTH], described <a href="formal_spec.html#merkletreeinclusionproof">here</a>;</li>
<li><code>identityPathIndex[DEPTH]</code> - pathIndex[DEPTH], described <a href="formal_spec.html#merkletreeinclusionproof">here</a>.</li>
</ul>
<p><strong>Public inputs</strong>:</p>
<ul>
<li><code>x</code> - <code>Hash(signal)</code>, where <code>signal</code> is for example message, that was sent by user;</li>
<li><code>externalNullifier</code> - <code>Hash(epoch, rln_identifier)</code>.</li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>y</code> - calculated first-degree linear polynomial (y = kx + b);</li>
<li><code>root</code> - root of the Merkle Tree;</li>
<li><code>nullifier</code> - internal nullifier/pseudonym of the user in anonyomus environment.</li>
</ul>
<p><strong>Logic/Constraints</strong>:</p>
<ol>
<li>Merkle tree membership check:
<ul>
<li><code>identityCommitment</code> = <code>Poseidon(identitySecret, )</code> calculation;</li>
<li><code>rateCommitment</code> = <code>Poseidon(identityCommitment, userMessageLimit)</code> calculation;</li>
<li><a href="formal_spec.html#merkletreeinclusionproof">Merkle tree inclusion check</a> for the <code>rateCommitment</code>.</li>
</ul>
</li>
<li>Range check:
<ul>
<li><a href="formal_spec.html#isininterval">Range check</a> that <code>1 &lt;= messageId &lt;= userMessageLimit</code>.</li>
</ul>
</li>
<li>Polynomial share calculation:
<ul>
<li><code>a1</code> = <code>Poseidon(identitySecret, externalNullifier, messageId)</code>;</li>
<li><code>y</code> = <code>identitySecret + a1 * x</code>.</li>
</ul>
</li>
<li>Output of calculated <code>root</code>, <code>share</code> and <code>nullifier</code> = <code>Poseidon(a_1)</code> values.</li>
<li>Output of calculated \(root\), \(y = share\) and \(nullifier = Poseidon(a_1)\) values.</li>
</ol>
<hr />
<h3 id="withdrawal"><a class="header" href="#withdrawal">Withdrawal</a></h3>
<p><a href="https://github.com/Rate-Limiting-Nullifier/rln-circuits-v2/blob/main/circuits/withdraw.circom">withdraw.circom</a> is a template that's used for the withdrawal/slashing and is needed to prevent front run while withdrawing the stake from the smart-contract/registry. </p>
<p><a href="https://github.com/Rate-Limiting-Nullifier/circom-rln/blob/main/circuits/withdraw.circom">withdraw.circom</a> is a circuit that's used for the withdrawal/slashing and is needed to prevent frontrun while withdrawing the stake from the smart-contract/registry. </p>
<p><strong>Private inputs</strong>:</p>
<ul>
<li><code>identitySecret</code> - randomly generated number in <code>F_p</code>, used as private key.</li>
<li>\(identitySecret\) - randomly generated number in \(\mathbb{F_p}\), used as private key.</li>
</ul>
<p><strong>Public inputs</strong>:</p>
<ul>
<li><code>addressHash</code> - <code>F_p</code> scalar field element. <code>addressHash</code> = <code>Hash(address)</code>, where <code>address</code> is ETH address that'll receive stake. </li>
<li>\(address\) - \(\mathbb{F_p}\) scalar field element; denotes ETH address that'll receive stake. </li>
</ul>
<p><strong>Outputs</strong>:</p>
<ul>
<li><code>identityCommitment</code> = <code>Poseidon(identitySecret)</code>.</li>
<li>\(identityCommitment = Poseidon(identitySecret)\).</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="smart-contract"><a class="header" href="#smart-contract">Smart-contract</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="uses"><a class="header" href="#uses">Uses</a></h1>
<p>This section contains list of apps that use <strong>RLN</strong>:</p>
<ul>
@@ -555,6 +440,9 @@ So, the shares are: \((5, 55), (8, 70), (16, 110)\)</li>
<p>We can take any two shares to recover (as described in the interpolation section) the &quot;secret&quot; polynomial. Zero coefficient (\(a_0\)) in the recovered polynomial is the secret \(S\).</p>
<h2 id="important-notes"><a class="header" href="#important-notes">Important notes</a></h2>
<p>Arithmetic in this topic is usual for us. However, in real life, <strong>SSS</strong> arithmetic is defined over some finite field. This means that all calculations are carried out modulo some big prime field. In fact, it happens by itself in Circom because the arithmetic there is defined over the finite field, too, so we don't need to do anything extra). </p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="research"><a class="header" href="#research">Research</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="kzg-rln"><a class="header" href="#kzg-rln">KZG-RLN</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="noir-rln"><a class="header" href="#noir-rln">Noir-RLN</a></h1>
</main>

View File

@@ -3,7 +3,7 @@
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Protocol spec V1 - Rate-Limiting Nullifier</title>
<title>RLN in details - Rate-Limiting Nullifier</title>
<!-- Custom HTML head -->
@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html" class="active"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html" class="active"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -214,7 +214,7 @@ We denote: \(x = Poseidon(message), y = A(x)\). </p>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="protocol_spec_v2.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next" href="formal_spec.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
@@ -228,7 +228,7 @@ We denote: \(x = Poseidon(message), y = A(x)\). </p>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="protocol_spec_v2.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a rel="next" href="formal_spec.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>

225
research.html Normal file
View File

@@ -0,0 +1,225 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Research - Rate-Limiting Nullifier</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- MathJax -->
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
</head>
<body>
<div id="body-container">
<!-- Provide site root to javascript -->
<script>
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var html = document.querySelector('html');
var sidebar = null;
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html" class="active"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<!-- Track and set sidebar scroll position -->
<script>
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
sidebarScrollbox.addEventListener('click', function(e) {
if (e.target.tagName === 'A') {
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
}
}, { passive: true });
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
sessionStorage.removeItem('sidebar-scroll');
if (sidebarScrollTop) {
// preserve sidebar scroll position when navigating via links within sidebar
sidebarScrollbox.scrollTop = sidebarScrollTop;
} else {
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
var activeSection = document.querySelector('#sidebar .active');
if (activeSection) {
activeSection.scrollIntoView({ block: 'center' });
}
}
</script>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Rate-Limiting Nullifier</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="research"><a class="header" href="#research">Research</a></h1>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="sss.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="kzg_rln.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="sss.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="kzg_rln.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js"></script>
<script src="mark.min.js"></script>
<script src="searcher.js"></script>
<script src="clipboard.min.js"></script>
<script src="highlight.js"></script>
<script src="book.js"></script>
<!-- Custom JS scripts -->
<script src="mermaid.min.js"></script>
<script src="mermaid-init.js"></script>
</div>
</body>
</html>

View File

@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html" class="active"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html" class="active"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

225
smart_contract.html Normal file
View File

@@ -0,0 +1,225 @@
<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Smart-contract - Rate-Limiting Nullifier</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<!-- MathJax -->
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
</head>
<body>
<div id="body-container">
<!-- Provide site root to javascript -->
<script>
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var html = document.querySelector('html');
var sidebar = null;
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html" class="active"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<!-- Track and set sidebar scroll position -->
<script>
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
sidebarScrollbox.addEventListener('click', function(e) {
if (e.target.tagName === 'A') {
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
}
}, { passive: true });
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
sessionStorage.removeItem('sidebar-scroll');
if (sidebarScrollTop) {
// preserve sidebar scroll position when navigating via links within sidebar
sidebarScrollbox.scrollTop = sidebarScrollTop;
} else {
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
var activeSection = document.querySelector('#sidebar .active');
if (activeSection) {
activeSection.scrollIntoView({ block: 'center' });
}
}
</script>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Rate-Limiting Nullifier</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="smart-contract"><a class="header" href="#smart-contract">Smart-contract</a></h1>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="formal_spec.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="uses.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="formal_spec.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="uses.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js"></script>
<script src="mark.min.js"></script>
<script src="searcher.js"></script>
<script src="clipboard.min.js"></script>
<script src="highlight.js"></script>
<script src="book.js"></script>
<!-- Custom JS scripts -->
<script src="mermaid.min.js"></script>
<script src="mermaid-init.js"></script>
</div>
</body>
</html>

View File

@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html" class="active"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html" class="active"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -225,6 +225,9 @@ So, the shares are: \((5, 55), (8, 70), (16, 110)\)</li>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="research.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
@@ -236,6 +239,9 @@ So, the shares are: \((5, 55), (8, 70), (16, 110)\)</li>
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="research.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>

View File

@@ -3,7 +3,7 @@
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>Uses - Rate-Limiting Nullifier</title>
<title>RLN Uses - Rate-Limiting Nullifier</title>
<!-- Custom HTML head -->
@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html" class="active"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html" class="active"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -181,7 +181,7 @@
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="formal_spec.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="smart_contract.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
@@ -195,7 +195,7 @@
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="formal_spec.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<a rel="prev" href="smart_contract.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>

View File

@@ -85,7 +85,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html" class="active"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> Protocol spec V1</a></li><li class="chapter-item expanded "><a href="protocol_spec_v2.html"><strong aria-hidden="true">2.3.</strong> Protocol spec V2</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.4.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li></ol>
<ol class="chapter"><li class="chapter-item expanded "><a href="rln.html"><strong aria-hidden="true">1.</strong> RLN</a></li><li class="chapter-item expanded "><a href="overview.html"><strong aria-hidden="true">2.</strong> Overview</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="what_is_rln.html" class="active"><strong aria-hidden="true">2.1.</strong> What is RLN</a></li><li class="chapter-item expanded "><a href="protocol_spec.html"><strong aria-hidden="true">2.2.</strong> RLN in details</a></li><li class="chapter-item expanded "><a href="formal_spec.html"><strong aria-hidden="true">2.3.</strong> Formal spec</a></li><li class="chapter-item expanded "><a href="smart_contract.html"><strong aria-hidden="true">2.4.</strong> Smart-contract</a></li><li class="chapter-item expanded "><a href="uses.html"><strong aria-hidden="true">2.5.</strong> RLN Uses</a></li></ol></li><li class="chapter-item expanded "><a href="sss.html"><strong aria-hidden="true">3.</strong> Shamir's Secret Sharing</a></li><li class="chapter-item expanded "><a href="research.html"><strong aria-hidden="true">4.</strong> Research</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="kzg_rln.html"><strong aria-hidden="true">4.1.</strong> KZG-RLN</a></li><li class="chapter-item expanded "><a href="noir_rln.html"><strong aria-hidden="true">4.2.</strong> Noir-RLN</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -184,18 +184,20 @@
<h3 id="registration"><a class="header" href="#registration">Registration</a></h3>
<p>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: </p>
<p>\[identityCommitment = Poseidon(secretKey)\]</p>
<p>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 <strong>RLN</strong>, 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.</p>
<p>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 <strong>RLN</strong>, 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. Based on the stake amount apps can derive what's the messageLimit (\(userMessageLimit\)) for a user. Then the rateCommitment:</p>
<p>\[rateCommitment = Poseidon(identitytCommitment, userMessageLimit)\]</p>
<p>will be stored in the membership Merkle tree.</p>
<h3 id="interaction"><a class="header" href="#interaction">Interaction</a></h3>
<p>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.</p>
<p>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 (or specifically rate commitment) is the part of the membership Merkle tree.</p>
<p>There are a number of use-cases for <strong>RLN</strong>, 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.</p>
<p>The general anti-spam rule is usually in the form of:
<code>Users must not make more than X interactions per epoch.</code></p>
<p>The epoch can be translated as a time interval of <code>Y</code> units of time unit <code>Z</code>. For simplicity's sake, let's transform the rule into: `Users must not send more than one message per second.</p>
<p>We can implement this using <em>Shamir's Secret Sharing</em> scheme (<a href="./sss.html"><em>read more</em></a>), which allows you to split a secret (f.e. to <code>n</code> parts) and recover it when any <code>m</code> of <code>n</code> parts <code>(m &lt;= n)</code> are presented.</p>
<p>Thus, users have to split their <code>secret_key</code> into <code>n</code> parts, and for every interaction, they have to reveal the new part of the <code>secret_key.</code> So, in addition to proving the membership in the <em>Merkle Tree</em>, users have to prove that the revealed part is truly the part of their <code>secret_key.</code></p>
<p>The general anti-spam rule is usually in the form of: <em>users must not make more than X interactions per epoch</em>.</p>
<p>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: <em>users must not send more than one message per second</em>.</p>
<p>We can implement this using <a href="./sss.html"><em>Shamir's Secret Sharing (SSS)</em> scheme</a>, which allows you to split a secret to \(n\) parts and recover it when any \(m\) of \(n\) parts \(m \le n\) are presented.</p>
<p>Thus, users have to split their secret key into \(n\) parts, and for each interaction, they have to reveal the new part of the secret key. So, in addition to proving the membership, users have to prove that the revealed part is truly the part of their secret key.</p>
<p>If they make more interactions than allowed per epoch, their secret key can be fully reconstructed.</p>
<h3 id="withdrawal-or-slashing"><a class="header" href="#withdrawal-or-slashing">Withdrawal (or slashing)</a></h3>
<p>The final property of the <strong>RLN</strong> 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 <strong>RLN</strong> 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.</p>
<p>The final property of the <strong>RLN</strong> mechanism is that it allows for the users to be removed from the
membership tree by anyone that knows their secret key. Thus, if someone spams, it'll be possible to recover the secret key and withdraw the stake (or <em>slash</em>) of a spammer - that's why it's economically inefficient for users to spam.</p>
</main>