docs: add Merkle Tree gadget explanation

This commit is contained in:
Magamedrasul Ibragimov
2022-10-03 16:23:16 +03:00
parent c84054b900
commit a7b37293ea
3 changed files with 76 additions and 1 deletions

View File

@@ -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`

View File

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

View File

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