mirror of https://github.com/vacp2p/rfc.git
chore(32-RLN): update v1 RFC (#581)
fix(32-RLN): change to stable version & rename to RLN-V1 chore(32-RLN): add SSS attack description chore(32-RLN): PR fixes chore(32-RLN): minor PR changes
This commit is contained in:
parent
c70a47f645
commit
c9052d1826
|
@ -1,14 +1,15 @@
|
||||||
---
|
---
|
||||||
slug: 32
|
slug: 32
|
||||||
title: 32/RLN
|
title: 32/RLN-V1
|
||||||
name: Rate Limit Nullifier
|
name: Rate Limit Nullifier
|
||||||
status: raw
|
status: raw
|
||||||
editor: Blagoj Dimovski <blagoj.dimovski@yandex.com>
|
editor: Rasul Ibragimov <curryrasul@gmail.com>
|
||||||
contributors:
|
contributors:
|
||||||
- Barry Whitehat <barrywhitehat@protonmail.com>
|
- Barry Whitehat <barrywhitehat@protonmail.com>
|
||||||
- Sanaz Taheri <sanaz@status.im>
|
- Sanaz Taheri <sanaz@status.im>
|
||||||
- Oskar Thorén <oskar@status.im>
|
- Oskar Thorén <oskar@status.im>
|
||||||
- Onur Kilic <onurkilic1004@gmail.com>
|
- Onur Kilic <onurkilic1004@gmail.com>
|
||||||
|
- Blagoj Dimovski <blagoj.dimovski@yandex.com>
|
||||||
---
|
---
|
||||||
|
|
||||||
# Abstract
|
# Abstract
|
||||||
|
@ -133,14 +134,13 @@ For proof generation,
|
||||||
the user need to submit the following fields to the circuit:
|
the user need to submit the following fields to the circuit:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
identity_secret: identity_secret_hash,
|
identity_secret: identity_secret_hash,
|
||||||
path_elements: Merkle_proof.path_elements,
|
path_elements: Merkle_proof.path_elements,
|
||||||
identity_path_index: Merkle_proof.indices,
|
identity_path_index: Merkle_proof.indices,
|
||||||
x: signal_hash,
|
x: signal_hash,
|
||||||
epoch: epoch,
|
external_nullifier: external_nullifier
|
||||||
rln_identifier: rln_identifier
|
}
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,8 +155,7 @@ The following fields are needed for proof output calculation:
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
identity_secret_hash: bigint,
|
identity_secret_hash: bigint,
|
||||||
epoch: bigint,
|
external_nullifier: bigint,
|
||||||
rln_identifier: bigint,
|
|
||||||
x: bigint,
|
x: bigint,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -164,8 +163,6 @@ The following fields are needed for proof output calculation:
|
||||||
The output `[y, internal_nullifier]` is calculated in the following way:
|
The output `[y, internal_nullifier]` is calculated in the following way:
|
||||||
|
|
||||||
```
|
```
|
||||||
external_nullifier = poseidonHash([epoch, rln_identifier])
|
|
||||||
|
|
||||||
a_0 = identity_secret_hash
|
a_0 = identity_secret_hash
|
||||||
a_1 = poseidonHash([a0, external_nullifier])
|
a_1 = poseidonHash([a0, external_nullifier])
|
||||||
|
|
||||||
|
@ -196,10 +193,10 @@ Additionally depending on the application,
|
||||||
the following fields might be required:
|
the following fields might be required:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
root: Merkle_proof.root,
|
root: Merkle_proof.root,
|
||||||
epoch: epoch
|
epoch: epoch
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,8 +262,7 @@ The `zk_proof` should be verified by providing the `zk_proof` field to the circu
|
||||||
Merkle_proof.root,
|
Merkle_proof.root,
|
||||||
internal_nullifier,
|
internal_nullifier,
|
||||||
x, # signal_hash
|
x, # signal_hash
|
||||||
epoch,
|
external_nullifier
|
||||||
rln_identifier
|
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -345,15 +341,14 @@ using the [circomlib](https://docs.circom.io/) library.
|
||||||
|
|
||||||
### System parameters
|
### System parameters
|
||||||
|
|
||||||
- `n_levels` - Merkle tree depth
|
- `DEPTH` - Merkle tree depth
|
||||||
|
|
||||||
|
|
||||||
### Circuit parameters
|
### Circuit parameters
|
||||||
|
|
||||||
**Public Inputs**
|
**Public Inputs**
|
||||||
- `x`
|
- `x`
|
||||||
- `epoch`
|
- `external_nullifier`
|
||||||
- `rln_identifier`
|
|
||||||
|
|
||||||
**Private Inputs**
|
**Private Inputs**
|
||||||
* `identity_secret_hash`
|
* `identity_secret_hash`
|
||||||
|
@ -443,9 +438,9 @@ The identity credentials of a user are composed of:
|
||||||
The `identity_secret` is generated in the following way:
|
The `identity_secret` is generated in the following way:
|
||||||
|
|
||||||
```
|
```
|
||||||
identity_nullifier = random_32_byte_buffer
|
identity_nullifier = random_32_byte_buffer
|
||||||
identity_trapdoor = random_32_byte_buffer
|
identity_trapdoor = random_32_byte_buffer
|
||||||
identity_secret = [identity_nullifier, identity_trapdoor]
|
identity_secret = [identity_nullifier, identity_trapdoor]
|
||||||
```
|
```
|
||||||
|
|
||||||
The same secret should not be used accross different protocols,
|
The same secret should not be used accross different protocols,
|
||||||
|
@ -456,7 +451,7 @@ because revealing the secret at one protocol could break privacy for the user in
|
||||||
The `identity_secret_hash` is generated by obtaining a Poseidon hash of the `identity_secret` array:
|
The `identity_secret_hash` is generated by obtaining a Poseidon hash of the `identity_secret` array:
|
||||||
|
|
||||||
```
|
```
|
||||||
identity_secret_hash = poseidonHash(identity_secret)
|
identity_secret_hash = poseidonHash(identity_secret)
|
||||||
```
|
```
|
||||||
|
|
||||||
### `identity_commitment`
|
### `identity_commitment`
|
||||||
|
@ -477,6 +472,16 @@ The standard for this is to use trusted [Multi-Party Computation (MPC)](https://
|
||||||
which requires two phases.
|
which requires two phases.
|
||||||
Trusted MPC ceremony has not yet been performed for the RLN circuits.
|
Trusted MPC ceremony has not yet been performed for the RLN circuits.
|
||||||
|
|
||||||
|
## SSS security assumptions
|
||||||
|
|
||||||
|
Shamir-Secret Sharing requires polynomial coefficients to be independent of each other.
|
||||||
|
However, `a_1` depends on `a_0` through the Poseidon hash algorithm.
|
||||||
|
Due to the design of Poseidon, it is possible to [attack](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627) the protocol.
|
||||||
|
It was decided *not* to change the circuits design, since at the moment the attack is infeasible. Therefore, implementers must be aware that the current version provides approximately 160-bit security and not 254.
|
||||||
|
Possible improvements:
|
||||||
|
* [change the circuit](https://github.com/Rate-Limiting-Nullifier/rln-circuits/pull/7#issuecomment-1416085627) to make coefficients independent;
|
||||||
|
* switch to other hash function (Keccak, SHA);
|
||||||
|
|
||||||
# Appendix B: Identity scheme choice
|
# Appendix B: Identity scheme choice
|
||||||
|
|
||||||
The hashing scheme used is based on the design decisions which also include the Semaphore circuits.
|
The hashing scheme used is based on the design decisions which also include the Semaphore circuits.
|
||||||
|
@ -499,9 +504,9 @@ To achieve the above interoperability UX while preventing the shared app securit
|
||||||
we had to do the follow in regard the identity secret and identity commitment:
|
we had to do the follow in regard the identity secret and identity commitment:
|
||||||
|
|
||||||
```
|
```
|
||||||
identity_secret = [identity_nullifier, identity_trapdoor]
|
identity_secret = [identity_nullifier, identity_trapdoor]
|
||||||
identity_secret_hash = poseidonHash(identity_secret)
|
identity_secret_hash = poseidonHash(identity_secret)
|
||||||
identity_commitment = poseidonHash([identity_secret_hash])
|
identity_commitment = poseidonHash([identity_secret_hash])
|
||||||
```
|
```
|
||||||
|
|
||||||
Secret components for generating Semaphore proof:
|
Secret components for generating Semaphore proof:
|
||||||
|
@ -554,82 +559,73 @@ The examples are written in [rust](https://www.rust-lang.org/).
|
||||||
## Creating a RLN object
|
## Creating a RLN object
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use rln::protocol::*;
|
use rln::protocol::*;
|
||||||
use rln::public::*;
|
use rln::public::*;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
// We set the RLN parameters:
|
||||||
// We set the RLN parameters:
|
// - the tree height;
|
||||||
// - the tree height;
|
// - the circuit resource folder (requires a trailing "/").
|
||||||
// - the circuit resource folder (requires a trailing "/").
|
let tree_height = 20;
|
||||||
let tree_height = 20;
|
let resources = Cursor::new("../zerokit/rln/resources/tree_height_20/");
|
||||||
let resources = Cursor::new("../zerokit/rln/resources/tree_height_20/");
|
// We create a new RLN instance
|
||||||
|
let mut rln = RLN::new(tree_height, resources);
|
||||||
// We create a new RLN instance
|
|
||||||
let mut rln = RLN::new(tree_height, resources);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Generating identity credentials
|
## Generating identity credentials
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// We generate an identity tuple
|
// We generate an identity tuple
|
||||||
let mut buffer = Cursor::new(Vec::<u8>::new());
|
let mut buffer = Cursor::new(Vec::<u8>::new());
|
||||||
rln.extended_key_gen(&mut buffer).unwrap();
|
rln.extended_key_gen(&mut buffer).unwrap();
|
||||||
|
// We deserialize the keygen output to obtain
|
||||||
// We deserialize the keygen output to obtain
|
// the identiy_secret and id_commitment
|
||||||
// the identiy_secret and id_commitment
|
let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) = deserialize_identity_tuple(buffer.into_inner());
|
||||||
let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) = deserialize_identity_tuple(buffer.into_inner());
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Adding ID commitment to the RLN Merkle tree
|
## Adding ID commitment to the RLN Merkle tree
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// We define the tree index where id_commitment will be added
|
// We define the tree index where id_commitment will be added
|
||||||
let id_index = 10;
|
let id_index = 10;
|
||||||
|
// We serialize id_commitment and pass it to set_leaf
|
||||||
// We serialize id_commitment and pass it to set_leaf
|
let mut buffer = Cursor::new(serialize_field_element(id_commitment));
|
||||||
let mut buffer = Cursor::new(serialize_field_element(id_commitment));
|
rln.set_leaf(id_index, &mut buffer).unwrap();
|
||||||
rln.set_leaf(id_index, &mut buffer).unwrap();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Setting epoch and signal
|
## Setting epoch and signal
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// We generate epoch from a date seed and we ensure is
|
// We generate epoch from a date seed and we ensure is
|
||||||
// mapped to a field element by hashing-to-field its content
|
// mapped to a field element by hashing-to-field its content
|
||||||
let epoch = hash_to_field(b"Today at noon, this year");
|
let epoch = hash_to_field(b"Today at noon, this year");
|
||||||
|
// We set our signal
|
||||||
// We set our signal
|
let signal = b"RLN is awesome";
|
||||||
let signal = b"RLN is awesome";
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Generating proof
|
## Generating proof
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// We prepare input to the proof generation routine
|
// We prepare input to the proof generation routine
|
||||||
let proof_input = prepare_prove_input(identity_secret, id_index, epoch, signal);
|
let proof_input = prepare_prove_input(identity_secret, id_index, epoch, signal);
|
||||||
|
// We generate a RLN proof for proof_input
|
||||||
// We generate a RLN proof for proof_input
|
let mut in_buffer = Cursor::new(proof_input);
|
||||||
let mut in_buffer = Cursor::new(proof_input);
|
let mut out_buffer = Cursor::new(Vec::<u8>::new());
|
||||||
let mut out_buffer = Cursor::new(Vec::<u8>::new());
|
rln.generate_rln_proof(&mut in_buffer, &mut out_buffer)
|
||||||
rln.generate_rln_proof(&mut in_buffer, &mut out_buffer)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
// We get the public outputs returned by the circuit evaluation
|
||||||
// We get the public outputs returned by the circuit evaluation
|
let proof_data = out_buffer.into_inner();
|
||||||
let proof_data = out_buffer.into_inner();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Verifiying proof
|
## Verifiying proof
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// We prepare input to the proof verification routine
|
// We prepare input to the proof verification routine
|
||||||
let verify_data = prepare_verify_input(proof_data, signal);
|
let verify_data = prepare_verify_input(proof_data, signal);
|
||||||
|
// We verify the zk-proof against the provided proof values
|
||||||
// We verify the zk-proof against the provided proof values
|
let mut in_buffer = Cursor::new(verify_data);
|
||||||
let mut in_buffer = Cursor::new(verify_data);
|
let verified = rln.verify(&mut in_buffer).unwrap();
|
||||||
let verified = rln.verify(&mut in_buffer).unwrap();
|
// We ensure the proof is valid
|
||||||
|
assert!(verified);
|
||||||
// We ensure the proof is valid
|
|
||||||
assert!(verified);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For more details please visit the [`zerokit`](https://github.com/vacp2p/zerokit) library.
|
For more details please visit the [`zerokit`](https://github.com/vacp2p/zerokit) library.
|
||||||
|
@ -652,3 +648,5 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public
|
||||||
- [10] https://ethresear.ch/t/gas-and-circuit-constraint-benchmarks-of-binary-and-quinary-incremental-merkle-trees-using-the-poseidon-hash-function/7446
|
- [10] https://ethresear.ch/t/gas-and-circuit-constraint-benchmarks-of-binary-and-quinary-incremental-merkle-trees-using-the-poseidon-hash-function/7446
|
||||||
- [11] https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
|
- [11] https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing
|
||||||
- [12] https://research.nccgroup.com/2020/06/24/security-considerations-of-zk-snark-parameter-multi-party-computation/
|
- [12] https://research.nccgroup.com/2020/06/24/security-considerations-of-zk-snark-parameter-multi-party-computation/
|
||||||
|
- [13] https://github.com/Rate-Limiting-Nullifier/rln-circuits/
|
||||||
|
- [14] https://rate-limiting-nullifier.github.io/rln-docs/
|
|
@ -8,7 +8,7 @@ bookMenuLevels: 1
|
||||||
- [24/STATUS-CURATION]({{< relref "/docs/rfcs/24/README.md" >}})
|
- [24/STATUS-CURATION]({{< relref "/docs/rfcs/24/README.md" >}})
|
||||||
- [28/STATUS-FEATURING]({{< relref "/docs/rfcs/28/README.md" >}})
|
- [28/STATUS-FEATURING]({{< relref "/docs/rfcs/28/README.md" >}})
|
||||||
- [31/WAKU2-ENR]({{< relref "/docs/rfcs/31/README.md" >}})
|
- [31/WAKU2-ENR]({{< relref "/docs/rfcs/31/README.md" >}})
|
||||||
- [32/RLN-SPEC]({{< relref "/docs/rfcs/32/README.md" >}})
|
- [32/RLN-V1-SPEC]({{< relref "/docs/rfcs/32/README.md" >}})
|
||||||
- [34/WAKU2-PEER-EXCHANGE]({{< relref "/docs/rfcs/34/README.md" >}})
|
- [34/WAKU2-PEER-EXCHANGE]({{< relref "/docs/rfcs/34/README.md" >}})
|
||||||
- [35/WAKU2-NOISE]({{< relref "/docs/rfcs/35/README.md" >}})
|
- [35/WAKU2-NOISE]({{< relref "/docs/rfcs/35/README.md" >}})
|
||||||
- [37/WAKU2-NOISE-SESSIONS]({{< relref "/docs/rfcs/37/README.md" >}})
|
- [37/WAKU2-NOISE-SESSIONS]({{< relref "/docs/rfcs/37/README.md" >}})
|
||||||
|
|
Loading…
Reference in New Issue