fix(rln): Remove resources folder, update missed docs (#246)

* remove resources folder, update missed docs

* refactor
This commit is contained in:
Ekaterina Broslavskaya 2024-05-10 18:13:00 +07:00 committed by GitHub
parent 652cc3647e
commit 4931b25237
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 105 additions and 131 deletions

View File

@ -3,6 +3,7 @@
This module provides APIs to manage, compute and verify [RLN](https://rfc.vac.dev/spec/32/) zkSNARK proofs and RLN primitives.
## Pre-requisites
### Install dependencies and clone repo
```sh
@ -14,6 +15,7 @@ cd zerokit/rln
### Build and Test
To build and test, run the following commands within the module folder
```bash
cargo make build
cargo make test
@ -21,11 +23,11 @@ cargo make test
### Compile ZK circuits
The `rln` (https://github.com/privacy-scaling-explorations/rln) repository, which contains the RLN circuit implementation is a submodule of zerokit RLN.
The `rln` (https://github.com/rate-limiting-nullifier/circom-rln) repository, which contains the RLN circuit implementation is a submodule of zerokit RLN.
To compile the RLN circuit
``` sh
```sh
# Update submodules
git submodule update --init --recursive
@ -52,10 +54,9 @@ include "./rln-base.circom";
component main {public [x, epoch, rln_identifier ]} = RLN(N);
```
However, if `N` is too big, this might require a bigger Powers of Tau ceremony than the one hardcoded in `./scripts/build-circuits.sh`, which is `2^14`.
However, if `N` is too big, this might require a bigger Powers of Tau ceremony than the one hardcoded in `./scripts/build-circuits.sh`, which is `2^14`.
In such case we refer to the official [Circom documentation](https://docs.circom.io/getting-started/proving-circuits/#powers-of-tau) for instructions on how to run an appropriate Powers of Tau ceremony and Phase 2 in order to compile the desired circuit.
Currently, the `rln` module comes with 2 [pre-compiled](https://github.com/vacp2p/zerokit/tree/master/rln/resources) RLN circuits having Merkle tree of height `20` and `32`, respectively.
## Getting started
@ -73,7 +74,7 @@ rln = { git = "https://github.com/vacp2p/zerokit" }
First, we need to create a RLN object for a chosen input Merkle tree size.
Note that we need to pass to RLN object constructor the path where the circuit (`rln.wasm`, built for the input tree size), the corresponding proving key (`rln_final.zkey`) and verification key (`verification_key.json`, optional) are found.
Note that we need to pass to RLN object constructor the path where the circuit (`rln.wasm`, built for the input tree size), the corresponding proving key (`rln_final.zkey`) or (`rln_final.arkzkey`) and verification key (`verification_key.json`, optional) are found.
In the following we will use [cursors](https://doc.rust-lang.org/std/io/struct.Cursor.html) as readers/writers for interfacing with RLN public APIs.
@ -82,14 +83,14 @@ use rln::protocol::*;
use rln::public::*;
use std::io::Cursor;
// We set the RLN parameters:
// We set the RLN parameters:
// - the tree height;
// - the circuit resource folder (requires a trailing "/").
// - the tree config, if it is not defined, the default value will be set
let tree_height = 20;
let resources = Cursor::new("../zerokit/rln/resources/tree_height_20/");
let input = Cursor::new(json!({}).to_string());
// We create a new RLN instance
let mut rln = RLN::new(tree_height, resources);
let mut rln = RLN::new(tree_height, input);
```
### Generate an identity keypair
@ -121,33 +122,43 @@ rln.set_leaf(id_index, &mut buffer).unwrap();
Note that when tree leaves are not explicitly set by the user (in this example, all those with index less and greater than `10`), their values is set to an hardcoded default (all-`0` bytes in current implementation).
### Set epoch
### Set external nullifier
The epoch, sometimes referred to as _external nullifier_, is used to identify messages received in a certain time frame. It usually corresponds to the current UNIX time but can also be set to a random value or generated by a seed, provided that it corresponds to a field element.
The `external nullifier` includes two parameters.
The first one is `epoch` and it's used to identify messages received in a certain time frame. It usually corresponds to the current UNIX time but can also be set to a random value or generated by a seed, provided that it corresponds to a field element.
The second one is `rln_identifier` and it's used to prevent a RLN ZK proof generated for one application to be re-used in another one.
```rust
// We generate epoch from a date seed and we ensure is
// mapped to a field element by hashing-to-field its content
let epoch = hash_to_field(b"Today at noon, this year");
// We generate rln_identifier from a date seed and we ensure is
// mapped to a field element by hashing-to-field its content
let rln_identifier = hash_to_field(b"test-rln-identifier");
let external_nullifier = poseidon_hash(&[epoch, rln_identifier]);
```
### Set signal
The signal is the message for which we are computing a RLN proof.
```rust
// We set our signal
// We set our signal
let signal = b"RLN is awesome";
```
### Generate a RLN proof
We prepare the input to the proof generation routine.
We prepare the input to the proof generation routine.
Input buffer is serialized as `[ identity_key | id_index | epoch | rln_identifier | user_message_limit | message_id | signal_len | signal ]`.
Input buffer is serialized as `[ identity_key | id_index | external_nullifier | user_message_limit | message_id | signal_len | signal ]`.
```rust
// We prepare input to the proof generation routine
let proof_input = prepare_prove_input(identity_secret_hash, id_index, epoch, rln_identifier, user_message_limit, message_id, signal);
let proof_input = prepare_prove_input(identity_secret_hash, id_index, external_nullifier, signal);
```
We are now ready to generate a RLN ZK proof along with the _public outputs_ of the ZK circuit evaluation.
@ -164,12 +175,11 @@ rln.generate_rln_proof(&mut in_buffer, &mut out_buffer)
let proof_data = out_buffer.into_inner();
```
The byte vector `proof_data` is serialized as `[ zk-proof | tree_root | epoch | share_x | share_y | nullifier | rln_identifier ]`.
The byte vector `proof_data` is serialized as `[ zk-proof | tree_root | external_nullifier | share_x | share_y | nullifier ]`.
### Verify a RLN proof
We prepare the input to the proof verification routine.
We prepare the input to the proof verification routine.
Input buffer is serialized as `[proof_data | signal_len | signal ]`, where `proof_data` is (computed as) the output obtained by `generate_rln_proof`.
@ -182,17 +192,21 @@ let mut in_buffer = Cursor::new(verify_data);
let verified = rln.verify(&mut in_buffer).unwrap();
```
We check if the proof verification was successful:
We check if the proof verification was successful:
```rust
// We ensure the proof is valid
assert!(verified);
```
## Get involved!
Zerokit RLN public and FFI APIs allow interaction with many more features than what briefly showcased above.
We invite you to check our API documentation by running
```rust
cargo doc --no-deps
```
and look at unit tests to have an hint on how to interface and use them.
and look at unit tests to have an hint on how to interface and use them.

View File

@ -1,12 +1,11 @@
use criterion::{criterion_group, criterion_main, Criterion};
use rln::circuit::TEST_RESOURCES_FOLDER;
// Depending on the key type (enabled by the `--features arkzkey` flag)
// the upload speed from the `rln_final.zkey` or `rln_final.arkzkey` file is calculated
pub fn key_load_benchmark(c: &mut Criterion) {
c.bench_function("zkey::upload_from_folder", |b| {
b.iter(|| {
let _ = rln::circuit::zkey_from_folder(TEST_RESOURCES_FOLDER);
let _ = rln::circuit::zkey_from_folder();
})
});
}

View File

@ -26,7 +26,7 @@ cfg_if! {
cfg_if! {
if #[cfg(feature = "arkzkey")] {
use ark_zkey::read_arkzkey_from_bytes;
const ARKZKEY_FILENAME: &str = "rln_final.arkzkey";
const ARKZKEY_FILENAME: &str = "tree_height_20/rln_final.arkzkey";
} else {
use std::io::Cursor;
@ -34,12 +34,11 @@ cfg_if! {
}
}
const ZKEY_FILENAME: &str = "rln_final.zkey";
const VK_FILENAME: &str = "verification_key.json";
const WASM_FILENAME: &str = "rln.wasm";
const ZKEY_FILENAME: &str = "tree_height_20/rln_final.zkey";
const VK_FILENAME: &str = "tree_height_20/verification_key.json";
const WASM_FILENAME: &str = "tree_height_20/rln.wasm";
pub const TEST_TREE_HEIGHT: usize = 20;
pub const TEST_RESOURCES_FOLDER: &str = "tree_height_20";
#[cfg(not(target_arch = "wasm32"))]
static RESOURCES_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/resources");
@ -75,13 +74,11 @@ pub fn zkey_from_raw(zkey_data: &Vec<u8>) -> Result<(ProvingKey<Curve>, Constrai
// Loads the proving key
#[cfg(not(target_arch = "wasm32"))]
pub fn zkey_from_folder(
resources_folder: &str,
) -> Result<(ProvingKey<Curve>, ConstraintMatrices<Fr>)> {
pub fn zkey_from_folder() -> Result<(ProvingKey<Curve>, ConstraintMatrices<Fr>)> {
#[cfg(feature = "arkzkey")]
let zkey = RESOURCES_DIR.get_file(Path::new(resources_folder).join(ARKZKEY_FILENAME));
let zkey = RESOURCES_DIR.get_file(Path::new(ARKZKEY_FILENAME));
#[cfg(not(feature = "arkzkey"))]
let zkey = RESOURCES_DIR.get_file(Path::new(resources_folder).join(ZKEY_FILENAME));
let zkey = RESOURCES_DIR.get_file(Path::new(ZKEY_FILENAME));
if let Some(zkey) = zkey {
let proving_key_and_matrices = match () {
@ -117,9 +114,9 @@ pub fn vk_from_raw(vk_data: &[u8], zkey_data: &Vec<u8>) -> Result<VerifyingKey<C
// Loads the verification key
#[cfg(not(target_arch = "wasm32"))]
pub fn vk_from_folder(resources_folder: &str) -> Result<VerifyingKey<Curve>> {
let vk = RESOURCES_DIR.get_file(Path::new(resources_folder).join(VK_FILENAME));
let zkey = RESOURCES_DIR.get_file(Path::new(resources_folder).join(ZKEY_FILENAME));
pub fn vk_from_folder() -> Result<VerifyingKey<Curve>> {
let vk = RESOURCES_DIR.get_file(Path::new(VK_FILENAME));
let zkey = RESOURCES_DIR.get_file(Path::new(ZKEY_FILENAME));
let verifying_key: VerifyingKey<Curve>;
if let Some(vk) = vk {
@ -128,7 +125,7 @@ pub fn vk_from_folder(resources_folder: &str) -> Result<VerifyingKey<Curve>> {
))?)?;
Ok(verifying_key)
} else if let Some(_zkey) = zkey {
let (proving_key, _matrices) = zkey_from_folder(resources_folder)?;
let (proving_key, _matrices) = zkey_from_folder()?;
verifying_key = proving_key.vk;
Ok(verifying_key)
} else {
@ -152,9 +149,9 @@ pub fn circom_from_raw(wasm_buffer: Vec<u8>) -> Result<&'static Mutex<WitnessCal
// Initializes the witness calculator
#[cfg(not(target_arch = "wasm32"))]
pub fn circom_from_folder(resources_folder: &str) -> Result<&'static Mutex<WitnessCalculator>> {
pub fn circom_from_folder() -> Result<&'static Mutex<WitnessCalculator>> {
// We read the wasm file
let wasm = RESOURCES_DIR.get_file(Path::new(resources_folder).join(WASM_FILENAME));
let wasm = RESOURCES_DIR.get_file(Path::new(WASM_FILENAME));
if let Some(wasm) = wasm {
let wasm_buffer = wasm.contents();
@ -277,11 +274,8 @@ fn vk_from_vector(vk: &[u8]) -> Result<VerifyingKey<Curve>> {
// Checks verification key to be correct with respect to proving key
#[cfg(not(target_arch = "wasm32"))]
pub fn check_vk_from_zkey(
resources_folder: &str,
verifying_key: VerifyingKey<Curve>,
) -> Result<()> {
let (proving_key, _matrices) = zkey_from_folder(resources_folder)?;
pub fn check_vk_from_zkey(verifying_key: VerifyingKey<Curve>) -> Result<()> {
let (proving_key, _matrices) = zkey_from_folder()?;
if proving_key.vk == verifying_key {
Ok(())
} else {

View File

@ -19,7 +19,7 @@ cfg_if! {
if #[cfg(not(target_arch = "wasm32"))] {
use std::default::Default;
use std::sync::Mutex;
use crate::circuit::{circom_from_folder, vk_from_folder, circom_from_raw, zkey_from_folder, TEST_RESOURCES_FOLDER, TEST_TREE_HEIGHT};
use crate::circuit::{circom_from_folder, vk_from_folder, circom_from_raw, zkey_from_folder, TEST_TREE_HEIGHT};
use ark_circom::WitnessCalculator;
use serde_json::{json, Value};
use utils::{Hasher};
@ -58,18 +58,16 @@ impl RLN<'_> {
///
/// Input parameters are
/// - `tree_height`: the height of the internal Merkle tree
/// - `input_data`: include next parameters
/// - `resources_folder`: a reader for the string path of the resource folder containing the ZK circuit (`rln.wasm`), the proving key (`rln_final.zkey`) or (`rln_final.arkzkey`) and the verification key (`verification_key.json`).
/// - `tree_config`: a reader for a string containing a json with the merkle tree configuration
/// - `input_data`: include `tree_config` a reader for a string containing a json with the merkle tree configuration
/// Example:
/// ```
/// use std::io::Cursor;
///
/// let tree_height = 20;
/// let resources = Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());;
/// let input = Cursor::new(json!({}).to_string());;
///
/// // We create a new RLN instance
/// let mut rln = RLN::new(tree_height, resources);
/// let mut rln = RLN::new(tree_height, input);
/// ```
#[cfg(not(target_arch = "wasm32"))]
pub fn new<R: Read>(tree_height: usize, mut input_data: R) -> Result<RLN<'static>> {
@ -78,15 +76,12 @@ impl RLN<'_> {
input_data.read_to_end(&mut input)?;
let rln_config: Value = serde_json::from_str(&String::from_utf8(input)?)?;
let resources_folder = rln_config["resources_folder"]
.as_str()
.unwrap_or(TEST_RESOURCES_FOLDER);
let tree_config = rln_config["tree_config"].to_string();
let witness_calculator = circom_from_folder(resources_folder)?;
let proving_key = zkey_from_folder(resources_folder)?;
let witness_calculator = circom_from_folder()?;
let proving_key = zkey_from_folder()?;
let verification_key = vk_from_folder(resources_folder)?;
let verification_key = vk_from_folder()?;
let tree_config: <PoseidonTree as ZerokitMerkleTree>::Config = if tree_config.is_empty() {
<PoseidonTree as ZerokitMerkleTree>::Config::default()
@ -1204,7 +1199,7 @@ impl RLN<'_> {
impl Default for RLN<'_> {
fn default() -> Self {
let tree_height = TEST_TREE_HEIGHT;
let buffer = Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let buffer = Cursor::new(json!({}).to_string());
Self::new(tree_height, buffer).unwrap()
}
}

View File

@ -1,4 +1,4 @@
use crate::circuit::{Curve, Fr, TEST_RESOURCES_FOLDER, TEST_TREE_HEIGHT};
use crate::circuit::{Curve, Fr, TEST_TREE_HEIGHT};
use crate::hashers::{hash_to_field, poseidon_hash as utils_poseidon_hash};
use crate::protocol::*;
use crate::public::RLN;
@ -28,9 +28,7 @@ fn test_merkle_operations() {
}
// We create a new tree
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We first add leaves one by one specifying the index
for (i, leaf) in leaves.iter().enumerate() {
@ -124,9 +122,7 @@ fn test_leaf_setting_with_index() {
let set_index = rng.gen_range(0..no_of_leaves) as usize;
// We create a new tree
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We add leaves in a batch into the tree
let mut buffer = Cursor::new(vec_fr_to_bytes_le(&leaves).unwrap());
@ -196,9 +192,7 @@ fn test_atomic_operation() {
}
// We create a new tree
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We add leaves in a batch into the tree
let mut buffer = Cursor::new(vec_fr_to_bytes_le(&leaves).unwrap());
@ -247,9 +241,7 @@ fn test_atomic_operation_zero_indexed() {
}
// We create a new tree
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We add leaves in a batch into the tree
let mut buffer = Cursor::new(vec_fr_to_bytes_le(&leaves).unwrap());
@ -293,9 +285,7 @@ fn test_atomic_operation_consistency() {
}
// We create a new tree
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We add leaves in a batch into the tree
let mut buffer = Cursor::new(vec_fr_to_bytes_le(&leaves).unwrap());
@ -348,9 +338,7 @@ fn test_set_leaves_bad_index() {
let bad_index = (1 << tree_height) - rng.gen_range(0..no_of_leaves) as usize;
// We create a new tree
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// Get root of empty tree
let mut buffer = Cursor::new(Vec::<u8>::new());
@ -413,9 +401,7 @@ fn value_to_string_vec(value: &Value) -> Vec<String> {
fn test_groth16_proof_hardcoded() {
let tree_height = TEST_TREE_HEIGHT;
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let rln = RLN::new(tree_height, input_buffer).unwrap();
let rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
let valid_snarkjs_proof = json!({
"pi_a": [
@ -495,9 +481,7 @@ fn test_groth16_proof_hardcoded() {
fn test_groth16_proof() {
let tree_height = TEST_TREE_HEIGHT;
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// Note: we only test Groth16 proof generation, so we ignore setting the tree in the RLN object
let rln_witness = random_rln_witness(tree_height);
@ -543,9 +527,7 @@ fn test_rln_proof() {
}
// We create a new RLN instance
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We add leaves in a batch into the tree
let mut buffer = Cursor::new(vec_fr_to_bytes_le(&leaves).unwrap());
@ -588,11 +570,11 @@ fn test_rln_proof() {
rln.generate_rln_proof(&mut input_buffer, &mut output_buffer)
.unwrap();
// output_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let mut proof_data = output_buffer.into_inner();
// We prepare input for verify_rln_proof API
// input_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> | signal_len<8> | signal<var> ]
// input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal<var> ]
// that is [ proof_data || signal_len<8> | signal<var> ]
proof_data.append(&mut normalize_usize(signal.len()));
proof_data.append(&mut signal.to_vec());
@ -616,9 +598,7 @@ fn test_rln_with_witness() {
}
// We create a new RLN instance
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We add leaves in a batch into the tree
let mut buffer = Cursor::new(vec_fr_to_bytes_le(&leaves).unwrap());
@ -693,11 +673,11 @@ fn test_rln_with_witness() {
)
.unwrap();
// output_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let mut proof_data = output_buffer.into_inner();
// We prepare input for verify_rln_proof API
// input_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> | signal_len<8> | signal<var> ]
// input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal<var> ]
// that is [ proof_data || signal_len<8> | signal<var> ]
proof_data.append(&mut normalize_usize(signal.len()));
proof_data.append(&mut signal.to_vec());
@ -722,9 +702,7 @@ fn proof_verification_with_roots() {
}
// We create a new RLN instance
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We add leaves in a batch into the tree
let mut buffer = Cursor::new(vec_fr_to_bytes_le(&leaves).unwrap());
@ -751,7 +729,7 @@ fn proof_verification_with_roots() {
let external_nullifier = utils_poseidon_hash(&[epoch, rln_identifier]);
// We prepare input for generate_rln_proof API
// input_data is [ identity_secret<32> | id_index<8> | epoch<32> | rln_identifier<32> | user_message_limit<32> | message_id<32> | signal_len<8> | signal<var> ]
// input_data is [ identity_secret<32> | id_index<8> | external_nullifier<32> | user_message_limit<32> | message_id<32> | signal_len<8> | signal<var> ]
let mut serialized: Vec<u8> = Vec::new();
serialized.append(&mut fr_to_bytes_le(&identity_secret_hash));
serialized.append(&mut normalize_usize(identity_index));
@ -766,11 +744,11 @@ fn proof_verification_with_roots() {
rln.generate_rln_proof(&mut input_buffer, &mut output_buffer)
.unwrap();
// output_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// output_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let mut proof_data = output_buffer.into_inner();
// We prepare input for verify_rln_proof API
// input_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> | signal_len<8> | signal<var> ]
// input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal<var> ]
// that is [ proof_data || signal_len<8> | signal<var> ]
proof_data.append(&mut normalize_usize(signal.len()));
proof_data.append(&mut signal.to_vec());
@ -816,9 +794,7 @@ fn test_recover_id_secret() {
let tree_height = TEST_TREE_HEIGHT;
// We create a new RLN instance
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// Generate identity pair
let (identity_secret_hash, id_commitment) = keygen();
@ -953,9 +929,7 @@ fn test_get_leaf() {
// We generate a random tree
let tree_height = 10;
let mut rng = thread_rng();
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
// We generate a random leaf
let leaf = Fr::rand(&mut rng);
@ -980,9 +954,7 @@ fn test_get_leaf() {
fn test_valid_metadata() {
let tree_height = TEST_TREE_HEIGHT;
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap();
let mut rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
let arbitrary_metadata: &[u8] = b"block_number:200000";
rln.set_metadata(arbitrary_metadata).unwrap();
@ -998,9 +970,7 @@ fn test_valid_metadata() {
fn test_empty_metadata() {
let tree_height = TEST_TREE_HEIGHT;
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let rln = RLN::new(tree_height, input_buffer).unwrap();
let rln = RLN::new(tree_height, generate_input_buffer()).unwrap();
let mut buffer = Cursor::new(Vec::<u8>::new());
rln.get_metadata(&mut buffer).unwrap();

View File

@ -5,6 +5,8 @@ use ark_ff::PrimeField;
use color_eyre::{Report, Result};
use num_bigint::{BigInt, BigUint};
use num_traits::Num;
use serde_json::json;
use std::io::Cursor;
use std::iter::Extend;
pub fn to_bigint(el: &Fr) -> Result<BigInt> {
@ -179,6 +181,11 @@ pub fn normalize_usize(input: usize) -> Vec<u8> {
normalized_usize
}
// using for test
pub fn generate_input_buffer() -> Cursor<String> {
Cursor::new(json!({}).to_string())
}
/* Old conversion utilities between different libraries data types
// Conversion Utilities between poseidon-rs Field and arkworks Fr (in order to call directly poseidon-rs' poseidon_hash)

View File

@ -18,7 +18,7 @@ mod test {
fn create_rln_instance() -> &'static mut RLN<'static> {
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_config = json!({}).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(TEST_TREE_HEIGHT, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed");
@ -509,11 +509,11 @@ mod test {
serialized.append(&mut signal.to_vec());
// We call generate_rln_proof
// result_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let mut proof_data = rln_proof_gen(rln_pointer, serialized.as_ref());
// We prepare input for verify_rln_proof API
// input_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> | signal_len<8> | signal<var> ]
// input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal<var> ]
// that is [ proof_data | signal_len<8> | signal<var> ]
proof_data.append(&mut normalize_usize(signal.len()));
proof_data.append(&mut signal.to_vec());
@ -576,11 +576,11 @@ mod test {
serialized.append(&mut signal.to_vec());
// We call generate_rln_proof
// result_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let mut proof_data = rln_proof_gen(rln_pointer, serialized.as_ref());
// We prepare input for verify_rln_proof API
// input_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> | signal_len<8> | signal<var> ]
// input_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> | signal_len<8> | signal<var> ]
// that is [ proof_data | signal_len<8> | signal<var> ]
proof_data.append(&mut normalize_usize(signal.len()));
proof_data.append(&mut signal.to_vec());
@ -688,11 +688,11 @@ mod test {
serialized2.append(&mut signal2.to_vec());
// We call generate_rln_proof for first proof values
// result_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let proof_data_1 = rln_proof_gen(rln_pointer, serialized1.as_ref());
// We call generate_rln_proof
// result_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let proof_data_2 = rln_proof_gen(rln_pointer, serialized2.as_ref());
let input_proof_buffer_1 = &Buffer::from(proof_data_1.as_ref());
@ -746,7 +746,7 @@ mod test {
serialized.append(&mut signal3.to_vec());
// We call generate_rln_proof
// result_data is [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
// result_data is [ proof<128> | root<32> | external_nullifier<32> | x<32> | y<32> | nullifier<32> ]
let proof_data_3 = rln_proof_gen(rln_pointer, serialized.as_ref());
// We attempt to recover the secret using share1 (coming from identity_secret_hash) and share3 (coming from identity_secret_hash_new)

View File

@ -2,9 +2,7 @@
mod test {
use ark_ff::BigInt;
use rln::circuit::zkey_from_folder;
use rln::circuit::{
circom_from_folder, vk_from_folder, Fr, TEST_RESOURCES_FOLDER, TEST_TREE_HEIGHT,
};
use rln::circuit::{circom_from_folder, vk_from_folder, Fr, TEST_TREE_HEIGHT};
use rln::hashers::{hash_to_field, poseidon_hash};
use rln::poseidon_tree::PoseidonTree;
use rln::protocol::*;
@ -146,9 +144,9 @@ mod test {
// We test a RLN proof generation and verification
fn test_witness_from_json() {
// We generate all relevant keys
let proving_key = zkey_from_folder(TEST_RESOURCES_FOLDER).unwrap();
let verification_key = vk_from_folder(TEST_RESOURCES_FOLDER).unwrap();
let builder = circom_from_folder(TEST_RESOURCES_FOLDER).unwrap();
let proving_key = zkey_from_folder().unwrap();
let verification_key = vk_from_folder().unwrap();
let builder = circom_from_folder().unwrap();
// We compute witness from the json input example
let witness_json = WITNESS_JSON_20;
@ -205,9 +203,9 @@ mod test {
.unwrap();
// We generate all relevant keys
let proving_key = zkey_from_folder(TEST_RESOURCES_FOLDER).unwrap();
let verification_key = vk_from_folder(TEST_RESOURCES_FOLDER).unwrap();
let builder = circom_from_folder(TEST_RESOURCES_FOLDER).unwrap();
let proving_key = zkey_from_folder().unwrap();
let verification_key = vk_from_folder().unwrap();
let builder = circom_from_folder().unwrap();
// Let's generate a zkSNARK proof
let proof = generate_proof(builder, &proving_key, &rln_witness).unwrap();

View File

@ -3,12 +3,11 @@ mod test {
use ark_ff::BigInt;
use ark_std::{rand::thread_rng, UniformRand};
use rand::Rng;
use rln::circuit::{Fr, TEST_RESOURCES_FOLDER, TEST_TREE_HEIGHT};
use rln::circuit::{Fr, TEST_TREE_HEIGHT};
use rln::hashers::{hash_to_field, poseidon_hash as utils_poseidon_hash, ROUND_PARAMS};
use rln::protocol::{compute_tree_root, deserialize_identity_tuple};
use rln::public::{hash as public_hash, poseidon_hash as public_poseidon_hash, RLN};
use rln::utils::*;
use serde_json::json;
use std::io::Cursor;
#[test]
@ -17,9 +16,7 @@ mod test {
let leaf_index = 3;
let user_message_limit = 1;
let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(TEST_TREE_HEIGHT, input_buffer).unwrap();
let mut rln = RLN::new(TEST_TREE_HEIGHT, generate_input_buffer()).unwrap();
// generate identity
let identity_secret_hash = hash_to_field(b"test-merkle-proof");