mirror of
https://github.com/Rate-Limiting-Nullifier/rln-docs.git
synced 2026-01-07 22:43:52 -05:00
docs: add Merkle Tree gadget explanation
This commit is contained in:
@@ -1,3 +1,75 @@
|
||||
# Circuits
|
||||
|
||||
*[zkSNARK](https://vitalik.ca/general/2022/06/15/using_snarks.html) is used in the **RLN** core. Therefore, we need to represent the protocol in R1CS (as we use Groth16). Circom DSL was chosen for this. This section provides an explanation of **RLN** circuits.*
|
||||
|
||||
___
|
||||
|
||||
**RLN** circuits implement the logic described in [previous topic](./protocol_spec.md).
|
||||
|
||||
## Merkle Tree circuit
|
||||
|
||||
One of the key component of **RLN** is *Incremental Merkle Tree*.
|
||||
Let's look at the [implementation](https://github.com/privacy-scaling-explorations/rln/blob/master/circuits/incrementalMerkleTree.circom).
|
||||
|
||||
At the beginning of the file we denote that we use second version of Circom and include two helper *zk-gadgets*:
|
||||
```
|
||||
pragma circom 2.0.0;
|
||||
|
||||
include "../node_modules/circomlib/circuits/poseidon.circom";
|
||||
include "../node_modules/circomlib/circuits/mux1.circom";
|
||||
```
|
||||
|
||||
*Poseidon* gadget is just the implementation of *Poseidon* hash function; *mux1* gadget will be described later.
|
||||
|
||||
Next, we can see two implemented gadgets:
|
||||
|
||||
```
|
||||
template PoseidonHashT3() {
|
||||
var nInputs = 2;
|
||||
signal input inputs[nInputs];
|
||||
signal output out;
|
||||
|
||||
component hasher = Poseidon(nInputs);
|
||||
for (var i = 0; i < nInputs; i ++) {
|
||||
hasher.inputs[i] <== inputs[i];
|
||||
}
|
||||
out <== hasher.out;
|
||||
}
|
||||
|
||||
template HashLeftRight() {
|
||||
signal input left;
|
||||
signal input right;
|
||||
|
||||
signal output hash;
|
||||
|
||||
component hasher = PoseidonHashT3();
|
||||
left ==> hasher.inputs[0];
|
||||
right ==> hasher.inputs[1];
|
||||
|
||||
hash <== hasher.out;
|
||||
}
|
||||
```
|
||||
|
||||
These are helper gadgets to make the code more clean. *Poseidon* gadget is implemented with the ability to take a different number of arguments. We use `PoseidonHashT3()` to initialize it like a function with two arguments. And `HashLeftRight` use `PoseidonHashT3` in more "readable" way: it takes two inputs `left` and `right` and outputs the result of calculation.
|
||||
|
||||
Next comes the core of Merkle Tree gadget:
|
||||
```
|
||||
template MerkleTreeInclusionProof(n_levels) {
|
||||
signal input leaf;
|
||||
signal input path_index[n_levels];
|
||||
signal input path_elements[n_levels][1];
|
||||
signal output root;
|
||||
|
||||
component hashers[n_levels];
|
||||
component mux[n_levels];
|
||||
|
||||
signal levelHashes[n_levels + 1];
|
||||
levelHashes[0] <== leaf;
|
||||
|
||||
...
|
||||
|
||||
root <== levelHashes[n_levels];
|
||||
}
|
||||
```
|
||||
|
||||
Here we have three inputs: `leaf`, `path_index` and `path_elements`
|
||||
@@ -46,6 +46,8 @@ So, `rln_identifier` is just a random value, that's unique per **RLN** app. It's
|
||||
Now, imagine, there are a lot of users sending messages and after each received message we need to check if any member can be slashed. For that we use all combinations of received *shares* and try to recover the polynomial. This is naive and non-optimal way. What if we have some mechanism, which will tell us about the connection between a person and his messages, while not revealing him.
|
||||
For that we can use `nullifier`. `nullifier = Poseidon(a_1, rln_identifier)` and it's public, thus, if user sends more than one message, it will be immediately visible to everyone.
|
||||
|
||||
Also, in our example (and actually current [zk-chat](https://github.com/njofce/zk-chat) implementation) we use linear polynomial, but SSS allows us to use various degree polynomials, therefore we can implement a protocol, where more than one signal can be sent in one epoch. For that you can read [specification](https://hackmd.io/7GR5Vi28Rz2EpEmLK0E0Aw?view) by Blagoj; there are also [circuits](https://github.com/privacy-scaling-explorations/rln/tree/master/circuits) implemented for various degree poynomials too.
|
||||
|
||||
# Diagram
|
||||
|
||||
```mermaid
|
||||
|
||||
@@ -13,4 +13,5 @@ Signal | The message generated by a user. It is an arbitrary bit string that may
|
||||
Signal hash | Keccak hash of the signal, used as an input in the RLN circuit.
|
||||
RLN Identifier | Random finite field value unique per RLN app. It is used for additional cross-application security. The role of the RLN identifier is protection of the user secrets being compromised if signals are being generated with the same credentials at different apps.
|
||||
RLN membership tree | Merkle tree data structure, filled with identity commitments of the users. Serves as a data structure that ensures user registrations.
|
||||
Merkle proof | Proof that a user is member of the RLN membership tree.
|
||||
Merkle proof | Proof that a user is member of the RLN membership tree.
|
||||
zk-gadget |
|
||||
Reference in New Issue
Block a user