mirror of https://github.com/vacp2p/zerokit.git
refactor(RLN:) Remove dependencies and add new APIs (#45)
* refactor(rln): removing unused crates/dependencies * cargo fmt * refactor(rln): removed more dependencies; curve/fields as parameters * refactor(rln): use poseidon-rs hash instead of semaphore-rs poseidon * chore(rln): remove deps * refactor(rln): use exclusively arkworks Fr * refactor(rln): integrate poseidon-rs implementation to work with arkworks arithmetic * fix(rln): remove previous poseidon-rs wrapper * feat(rln): add features to select MT; remove prints if not in debug mode * fix(rln): collect test parameters in a vector * feat(RLN): add `new_with_params` (#36) Allows passing the wasm, zkey and verification key data as buffers, instead of using a path to a folder * chore(rln): simplify read wasm * fix(rln): remove unused dependencies * cargo fmt * fix(rln): update dependencies, fix commit * refactor(rln): restore ark-circom original dep Co-authored-by: Richard Ramos <info@richardramos.me>
This commit is contained in:
parent
1131b76a66
commit
4dc600d353
|
@ -1,7 +1,7 @@
|
|||
[submodule "rln/vendor/rln"]
|
||||
path = rln/vendor/rln
|
||||
ignore = dirty
|
||||
url = https://github.com/privacy-scaling-explorations/rln.git
|
||||
url = https://github.com/Rate-Limiting-Nullifier/rln_circuits
|
||||
[submodule "semaphore/vendor/semaphore"]
|
||||
path = semaphore/vendor/semaphore
|
||||
ignore = dirty
|
||||
|
|
|
@ -9,28 +9,34 @@ crate-type = ["cdylib", "rlib", "staticlib"]
|
|||
[dependencies]
|
||||
|
||||
# ZKP Generation
|
||||
ark-ec = { version = "0.3.0", default-features = false, features = ["parallel"] }
|
||||
ark-ff = { version = "0.3.0", default-features = false, features = ["parallel", "asm"] }
|
||||
ark-std = { version = "0.3.0", default-features = false, features = ["parallel"] }
|
||||
ark-bn254 = { version = "0.3.0" }
|
||||
ark-groth16 = { git = "https://github.com/arkworks-rs/groth16", rev = "765817f", features = ["parallel"] }
|
||||
ark-relations = { version = "0.3.0", default-features = false, features = [ "std" ] }
|
||||
ark-serialize = { version = "0.3.0", default-features = false }
|
||||
ark-circom = { git = "https://github.com/gakonst/ark-circom", features = ["circom-2"] }
|
||||
wasmer = { version = "2.0" }
|
||||
ark-circom = { git = "https://github.com/gakonst/ark-circom", rev = "06eb075", features = ["circom-2"] }
|
||||
#ark-circom = { git = "https://github.com/vacp2p/ark-circom", branch = "no-ethers-core", features = ["circom-2"] }
|
||||
wasmer = "2.3.0"
|
||||
|
||||
# error handling
|
||||
color-eyre = "0.5"
|
||||
color-eyre = "0.5.11"
|
||||
thiserror = "1.0.0"
|
||||
|
||||
# utilities
|
||||
hex-literal = "0.3"
|
||||
num-bigint = { version = "0.4", default-features = false, features = ["rand"] }
|
||||
once_cell = "1.8"
|
||||
cfg-if = "1.0"
|
||||
num-bigint = { version = "0.4.3", default-features = false, features = ["rand"] }
|
||||
num-traits = "0.2.11"
|
||||
once_cell = "1.14.0"
|
||||
rand = "0.8"
|
||||
tiny-keccak = "2.0.2"
|
||||
num-traits = "0.2.15"
|
||||
tiny-keccak = { version = "2.0.2", features = ["keccak"] }
|
||||
|
||||
# serialization
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
|
||||
serde_json = "1.0.48"
|
||||
serde_json = "1.0.48"
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
hex-literal = "0.3.4"
|
||||
|
||||
[features]
|
||||
fullmerkletree = []
|
||||
|
|
|
@ -11,7 +11,7 @@ use num_bigint::BigUint;
|
|||
use once_cell::sync::OnceCell;
|
||||
use serde_json::Value;
|
||||
use std::fs::File;
|
||||
use std::io::{Error, ErrorKind, Read, Result};
|
||||
use std::io::{Cursor, Error, ErrorKind, Result};
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Mutex;
|
||||
|
@ -22,18 +22,18 @@ const VK_FILENAME: &str = "verifying_key.json";
|
|||
const WASM_FILENAME: &str = "rln.wasm";
|
||||
|
||||
// These parameters are used for tests
|
||||
// Note that the circuit and keys in TEST_RESOURCES_FOLDER are compiled for Merkle trees of height 15 and 19
|
||||
// Changing these parameters to other values than these two defaults will cause zkSNARK proof verification to fail
|
||||
//pub const TEST_TREE_HEIGHT: usize = 15;
|
||||
//pub const TEST_RESOURCES_FOLDER: &str = "./resources/tree_height_15/";
|
||||
//pub const TEST_TREE_HEIGHT: usize = 19;
|
||||
//pub const TEST_RESOURCES_FOLDER: &str = "./resources/tree_height_19/";
|
||||
pub const TEST_TREE_HEIGHT: usize = 20;
|
||||
pub const TEST_RESOURCES_FOLDER: &str = "./resources/tree_height_20/";
|
||||
// Note that the circuit and keys in TEST_RESOURCES_FOLDER are compiled for Merkle trees of height 15, 19 and 20
|
||||
// Changing these parameters to other values than these defaults will cause zkSNARK proof verification to fail
|
||||
pub const TEST_PARAMETERS_INDEX: usize = 2;
|
||||
pub const TEST_TREE_HEIGHT: usize = [15, 19, 20][TEST_PARAMETERS_INDEX];
|
||||
pub const TEST_RESOURCES_FOLDER: &str = [
|
||||
"./resources/tree_height_15/",
|
||||
"./resources/tree_height_19/",
|
||||
"./resources/tree_height_20/",
|
||||
][TEST_PARAMETERS_INDEX];
|
||||
|
||||
// The following types define the pairing friendly elliptic curve, the underlying finite fields and groups default to this module
|
||||
// Note that proofs are serialized assuming Fr to be 4x8 = 32 bytes in size. Hence, changing to a curve with different encoding will make proof verification to fail
|
||||
|
||||
pub type Curve = Bn254;
|
||||
pub type Fr = ArkFr;
|
||||
pub type Fq = ArkFq;
|
||||
|
@ -43,9 +43,21 @@ pub type G1Projective = ArkG1Projective;
|
|||
pub type G2Affine = ArkG2Affine;
|
||||
pub type G2Projective = ArkG2Projective;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
// Loads the proving key using a bytes vector
|
||||
pub fn zkey_from_raw(zkey_data: &Vec<u8>) -> Result<(ProvingKey<Curve>, ConstraintMatrices<Fr>)> {
|
||||
if !zkey_data.is_empty() {
|
||||
let mut c = Cursor::new(zkey_data);
|
||||
let proving_key_and_matrices = read_zkey(&mut c)?;
|
||||
Ok(proving_key_and_matrices)
|
||||
} else {
|
||||
Err(Error::new(ErrorKind::NotFound, "No proving key found!"))
|
||||
}
|
||||
}
|
||||
|
||||
// Loads the proving key
|
||||
pub fn ZKEY(resources_folder: &str) -> Result<(ProvingKey<Curve>, ConstraintMatrices<Fr>)> {
|
||||
pub fn zkey_from_folder(
|
||||
resources_folder: &str,
|
||||
) -> Result<(ProvingKey<Curve>, ConstraintMatrices<Fr>)> {
|
||||
let zkey_path = format!("{resources_folder}{ZKEY_FILENAME}");
|
||||
if Path::new(&zkey_path).exists() {
|
||||
let mut file = File::open(&zkey_path)?;
|
||||
|
@ -56,9 +68,27 @@ pub fn ZKEY(resources_folder: &str) -> Result<(ProvingKey<Curve>, ConstraintMatr
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
// Loads the verification key from a bytes vector
|
||||
pub fn vk_from_raw(vk_data: &Vec<u8>, zkey_data: &Vec<u8>) -> Result<VerifyingKey<Curve>> {
|
||||
let verifying_key: VerifyingKey<Curve>;
|
||||
|
||||
if !vk_data.is_empty() {
|
||||
verifying_key = vk_from_vector(vk_data);
|
||||
Ok(verifying_key)
|
||||
} else if !zkey_data.is_empty() {
|
||||
let (proving_key, _matrices) = zkey_from_raw(zkey_data)?;
|
||||
verifying_key = proving_key.vk;
|
||||
Ok(verifying_key)
|
||||
} else {
|
||||
Err(Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"No proving/verification key found!",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Loads the verification key
|
||||
pub fn VK(resources_folder: &str) -> Result<VerifyingKey<Curve>> {
|
||||
pub fn vk_from_folder(resources_folder: &str) -> Result<VerifyingKey<Curve>> {
|
||||
let vk_path = format!("{resources_folder}{VK_FILENAME}");
|
||||
let zkey_path = format!("{resources_folder}{ZKEY_FILENAME}");
|
||||
|
||||
|
@ -68,7 +98,7 @@ pub fn VK(resources_folder: &str) -> Result<VerifyingKey<Curve>> {
|
|||
verifying_key = vk_from_json(&vk_path);
|
||||
Ok(verifying_key)
|
||||
} else if Path::new(&zkey_path).exists() {
|
||||
let (proving_key, _matrices) = ZKEY(resources_folder)?;
|
||||
let (proving_key, _matrices) = zkey_from_folder(resources_folder)?;
|
||||
verifying_key = proving_key.vk;
|
||||
Ok(verifying_key)
|
||||
} else {
|
||||
|
@ -81,32 +111,25 @@ pub fn VK(resources_folder: &str) -> Result<VerifyingKey<Curve>> {
|
|||
|
||||
static WITNESS_CALCULATOR: OnceCell<Mutex<WitnessCalculator>> = OnceCell::new();
|
||||
|
||||
// Loads the circuit WASM
|
||||
fn read_wasm(resources_folder: &str) -> Vec<u8> {
|
||||
let wasm_path = format!("{resources_folder}{WASM_FILENAME}");
|
||||
let mut wasm_file = File::open(&wasm_path).expect("no file found");
|
||||
let metadata = std::fs::metadata(&wasm_path).expect("unable to read metadata");
|
||||
let mut wasm_buffer = vec![0; metadata.len() as usize];
|
||||
wasm_file
|
||||
.read_exact(&mut wasm_buffer)
|
||||
.expect("buffer overflow");
|
||||
wasm_buffer
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
// Initializes the witness calculator
|
||||
pub fn CIRCOM(resources_folder: &str) -> &'static Mutex<WitnessCalculator> {
|
||||
// Initializes the witness calculator using a bytes vector
|
||||
pub fn circom_from_raw(wasm_buffer: Vec<u8>) -> &'static Mutex<WitnessCalculator> {
|
||||
WITNESS_CALCULATOR.get_or_init(|| {
|
||||
// We read the wasm file
|
||||
let wasm_buffer = read_wasm(resources_folder);
|
||||
let store = Store::default();
|
||||
let module = Module::from_binary(&store, &wasm_buffer).expect("wasm should be valid");
|
||||
let module = Module::new(&store, wasm_buffer).unwrap();
|
||||
let result =
|
||||
WitnessCalculator::from_module(module).expect("Failed to create witness calculator");
|
||||
Mutex::new(result)
|
||||
})
|
||||
}
|
||||
|
||||
// Initializes the witness calculator
|
||||
pub fn circom_from_folder(resources_folder: &str) -> &'static Mutex<WitnessCalculator> {
|
||||
// We read the wasm file
|
||||
let wasm_path = format!("{resources_folder}{WASM_FILENAME}");
|
||||
let wasm_buffer = std::fs::read(&wasm_path).unwrap();
|
||||
circom_from_raw(wasm_buffer)
|
||||
}
|
||||
|
||||
// The following function implementations are taken/adapted from https://github.com/gakonst/ark-circom/blob/1732e15d6313fe176b0b1abb858ac9e095d0dbd7/src/zkey.rs
|
||||
|
||||
// Utilities to convert a json verification key in a groth16::VerificationKey
|
||||
|
@ -182,11 +205,8 @@ fn json_to_g2(json: &Value, key: &str) -> G2Affine {
|
|||
G2Affine::from(G2Projective::new(x, y, z))
|
||||
}
|
||||
|
||||
// Computes the verification key from its JSON serialization
|
||||
fn vk_from_json(vk_path: &str) -> VerifyingKey<Curve> {
|
||||
let json = std::fs::read_to_string(vk_path).unwrap();
|
||||
let json: Value = serde_json::from_str(&json).unwrap();
|
||||
|
||||
// Converts JSON to a VerifyingKey
|
||||
fn to_verifying_key(json: serde_json::Value) -> VerifyingKey<Curve> {
|
||||
VerifyingKey {
|
||||
alpha_g1: json_to_g1(&json, "vk_alpha_1"),
|
||||
beta_g2: json_to_g2(&json, "vk_beta_2"),
|
||||
|
@ -196,8 +216,24 @@ fn vk_from_json(vk_path: &str) -> VerifyingKey<Curve> {
|
|||
}
|
||||
}
|
||||
|
||||
// Computes the verification key from its JSON serialization
|
||||
fn vk_from_json(vk_path: &str) -> VerifyingKey<Curve> {
|
||||
let json = std::fs::read_to_string(vk_path).unwrap();
|
||||
let json: Value = serde_json::from_str(&json).unwrap();
|
||||
|
||||
to_verifying_key(json)
|
||||
}
|
||||
|
||||
// Computes the verification key from a bytes vector containing its JSON serialization
|
||||
fn vk_from_vector(vk: &[u8]) -> VerifyingKey<Curve> {
|
||||
let json = String::from_utf8(vk.to_vec()).expect("Found invalid UTF-8");
|
||||
let json: Value = serde_json::from_str(&json).unwrap();
|
||||
|
||||
to_verifying_key(json)
|
||||
}
|
||||
|
||||
// Checks verification key to be correct with respect to proving key
|
||||
pub fn check_vk_from_zkey(resources_folder: &str, verifying_key: VerifyingKey<Curve>) {
|
||||
let (proving_key, _matrices) = ZKEY(resources_folder).unwrap();
|
||||
let (proving_key, _matrices) = zkey_from_folder(resources_folder).unwrap();
|
||||
assert_eq!(proving_key.vk, verifying_key);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,23 @@ pub extern "C" fn new(tree_height: usize, input_buffer: *const Buffer, ctx: *mut
|
|||
true
|
||||
}
|
||||
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn new_with_params(
|
||||
tree_height: usize,
|
||||
circom_buffer: *const Buffer,
|
||||
zkey_buffer: *const Buffer,
|
||||
vk_buffer: *const Buffer,
|
||||
ctx: *mut *mut RLN,
|
||||
) -> bool {
|
||||
let circom_data = <&[u8]>::from(unsafe { &*circom_buffer });
|
||||
let zkey_data = <&[u8]>::from(unsafe { &*zkey_buffer });
|
||||
let vk_data = <&[u8]>::from(unsafe { &*vk_buffer });
|
||||
let rln = RLN::new_with_params(tree_height, circom_data, zkey_data, vk_data);
|
||||
unsafe { *ctx = Box::into_raw(Box::new(rln)) };
|
||||
true
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Merkle tree APIs
|
||||
////////////////////////////////////////////////////////
|
||||
|
@ -251,6 +268,8 @@ mod test {
|
|||
use crate::utils::*;
|
||||
use ark_std::{rand::thread_rng, UniformRand};
|
||||
use rand::Rng;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
@ -578,6 +597,78 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Creating a RLN with raw data should generate same results as using a path to resources
|
||||
fn test_rln_raw_ffi() {
|
||||
let tree_height = TEST_TREE_HEIGHT;
|
||||
|
||||
// We create a RLN instance using a resource folder path
|
||||
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
|
||||
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes());
|
||||
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
|
||||
assert!(success, "RLN object creation failed");
|
||||
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
|
||||
|
||||
// We obtain the root from the RLN instance
|
||||
let mut output_buffer = MaybeUninit::<Buffer>::uninit();
|
||||
let success = get_root(rln_pointer, output_buffer.as_mut_ptr());
|
||||
assert!(success, "get root call failed");
|
||||
let output_buffer = unsafe { output_buffer.assume_init() };
|
||||
let result_data = <&[u8]>::from(&output_buffer).to_vec();
|
||||
let (root_rln_folder, _) = bytes_le_to_fr(&result_data);
|
||||
|
||||
// Reading the raw data from the files required for instantiating a RLN instance using raw data
|
||||
let circom_path = format!("./resources/tree_height_{TEST_TREE_HEIGHT}/rln.wasm");
|
||||
let mut circom_file = File::open(&circom_path).expect("no file found");
|
||||
let metadata = std::fs::metadata(&circom_path).expect("unable to read metadata");
|
||||
let mut circom_buffer = vec![0; metadata.len() as usize];
|
||||
circom_file
|
||||
.read_exact(&mut circom_buffer)
|
||||
.expect("buffer overflow");
|
||||
|
||||
let zkey_path = format!("./resources/tree_height_{TEST_TREE_HEIGHT}/rln_final.zkey");
|
||||
let mut zkey_file = File::open(&zkey_path).expect("no file found");
|
||||
let metadata = std::fs::metadata(&zkey_path).expect("unable to read metadata");
|
||||
let mut zkey_buffer = vec![0; metadata.len() as usize];
|
||||
zkey_file
|
||||
.read_exact(&mut zkey_buffer)
|
||||
.expect("buffer overflow");
|
||||
|
||||
let vk_path = format!("./resources/tree_height_{TEST_TREE_HEIGHT}/verification_key.json");
|
||||
|
||||
let mut vk_file = File::open(&vk_path).expect("no file found");
|
||||
let metadata = std::fs::metadata(&vk_path).expect("unable to read metadata");
|
||||
let mut vk_buffer = vec![0; metadata.len() as usize];
|
||||
vk_file.read_exact(&mut vk_buffer).expect("buffer overflow");
|
||||
|
||||
let circom_data = &Buffer::from(&circom_buffer[..]);
|
||||
let zkey_data = &Buffer::from(&zkey_buffer[..]);
|
||||
let vk_data = &Buffer::from(&vk_buffer[..]);
|
||||
|
||||
// Creating a RLN instance passing the raw data
|
||||
let mut rln_pointer_raw_bytes = MaybeUninit::<*mut RLN>::uninit();
|
||||
let success = new_with_params(
|
||||
tree_height,
|
||||
circom_data,
|
||||
zkey_data,
|
||||
vk_data,
|
||||
rln_pointer_raw_bytes.as_mut_ptr(),
|
||||
);
|
||||
assert!(success, "RLN object creation failed");
|
||||
let rln_pointer2 = unsafe { &mut *rln_pointer_raw_bytes.assume_init() };
|
||||
|
||||
// We obtain the root from the RLN instance containing raw data
|
||||
let mut output_buffer = MaybeUninit::<Buffer>::uninit();
|
||||
let success = get_root(rln_pointer2, output_buffer.as_mut_ptr());
|
||||
assert!(success, "get root call failed");
|
||||
let output_buffer = unsafe { output_buffer.assume_init() };
|
||||
let result_data = <&[u8]>::from(&output_buffer).to_vec();
|
||||
let (root_rln_raw, _) = bytes_le_to_fr(&result_data);
|
||||
|
||||
// And compare that the same root was generated
|
||||
assert_eq!(root_rln_folder, root_rln_raw);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Computes and verifies an RLN ZK proof using FFI APIs
|
||||
fn test_rln_proof_ffi() {
|
||||
|
|
|
@ -13,7 +13,10 @@ pub mod utils;
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use crate::circuit::{Fr, CIRCOM, TEST_RESOURCES_FOLDER, TEST_TREE_HEIGHT, VK, ZKEY};
|
||||
use crate::circuit::{
|
||||
circom_from_folder, vk_from_folder, zkey_from_folder, Fr, TEST_RESOURCES_FOLDER,
|
||||
TEST_TREE_HEIGHT,
|
||||
};
|
||||
use crate::poseidon_hash::poseidon_hash;
|
||||
use crate::poseidon_tree::PoseidonTree;
|
||||
use crate::protocol::*;
|
||||
|
@ -327,9 +330,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(TEST_RESOURCES_FOLDER).unwrap();
|
||||
let verification_key = VK(TEST_RESOURCES_FOLDER).unwrap();
|
||||
let builder = CIRCOM(TEST_RESOURCES_FOLDER);
|
||||
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);
|
||||
|
||||
// We compute witness from the json input example
|
||||
let mut witness_json: &str = "";
|
||||
|
@ -386,9 +389,9 @@ mod test {
|
|||
);
|
||||
|
||||
// We generate all relevant keys
|
||||
let proving_key = ZKEY(TEST_RESOURCES_FOLDER).unwrap();
|
||||
let verification_key = VK(TEST_RESOURCES_FOLDER).unwrap();
|
||||
let builder = CIRCOM(TEST_RESOURCES_FOLDER);
|
||||
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);
|
||||
|
||||
// Let's generate a zkSNARK proof
|
||||
let proof = generate_proof(builder, &proving_key, &rln_witness).unwrap();
|
||||
|
|
|
@ -5,13 +5,20 @@
|
|||
use crate::circuit::Fr;
|
||||
use crate::merkle_tree::*;
|
||||
use crate::poseidon_hash::poseidon_hash;
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
// The zerokit RLN default Merkle tree implementation.
|
||||
// To switch to FullMerkleTree implementation it is enough to redefine the following two types
|
||||
pub type PoseidonTree = OptimalMerkleTree<PoseidonHash>;
|
||||
pub type MerkleProof = OptimalMerkleProof<PoseidonHash>;
|
||||
//pub type PoseidonTree = FullMerkleTree<PoseidonHash>;
|
||||
//pub type MerkleProof = FullMerkleProof<PoseidonHash>;
|
||||
// The zerokit RLN default Merkle tree implementation is the OptimalMerkleTree.
|
||||
// To switch to FullMerkleTree implementation, it is enough to enable the fullmerkletree feature
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "fullmerkletree")] {
|
||||
pub type PoseidonTree = FullMerkleTree<PoseidonHash>;
|
||||
pub type MerkleProof = FullMerkleProof<PoseidonHash>;
|
||||
} else {
|
||||
pub type PoseidonTree = OptimalMerkleTree<PoseidonHash>;
|
||||
pub type MerkleProof = OptimalMerkleProof<PoseidonHash>;
|
||||
}
|
||||
}
|
||||
|
||||
// The zerokit RLN default Hasher
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
|
|
|
@ -12,6 +12,7 @@ use color_eyre::Result;
|
|||
use num_bigint::BigInt;
|
||||
use rand::Rng;
|
||||
use std::sync::Mutex;
|
||||
#[cfg(debug_assertions)]
|
||||
use std::time::Instant;
|
||||
use thiserror::Error;
|
||||
use tiny_keccak::{Hasher as _, Keccak};
|
||||
|
@ -415,6 +416,8 @@ pub fn generate_proof(
|
|||
.into_iter()
|
||||
.map(|(name, values)| (name.to_string(), values));
|
||||
|
||||
// If in debug mode, we measure and later print time take to compute witness
|
||||
#[cfg(debug_assertions)]
|
||||
let now = Instant::now();
|
||||
|
||||
let full_assignment = witness_calculator
|
||||
|
@ -423,6 +426,7 @@ pub fn generate_proof(
|
|||
.calculate_witness_element::<Curve, _>(inputs, false)
|
||||
.map_err(ProofError::WitnessError)?;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
println!("witness generation took: {:.2?}", now.elapsed());
|
||||
|
||||
// Random Values
|
||||
|
@ -430,7 +434,10 @@ pub fn generate_proof(
|
|||
let r = Fr::rand(&mut rng);
|
||||
let s = Fr::rand(&mut rng);
|
||||
|
||||
// If in debug mode, we measure and later print time take to compute proof
|
||||
#[cfg(debug_assertions)]
|
||||
let now = Instant::now();
|
||||
|
||||
let proof = create_proof_with_reduction_and_matrices::<_, CircomReduction>(
|
||||
&proving_key.0,
|
||||
r,
|
||||
|
@ -440,6 +447,8 @@ pub fn generate_proof(
|
|||
proving_key.1.num_constraints,
|
||||
full_assignment.as_slice(),
|
||||
)?;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
println!("proof generation took: {:.2?}", now.elapsed());
|
||||
|
||||
Ok(proof)
|
||||
|
@ -469,8 +478,14 @@ pub fn verify_proof(
|
|||
// Check that the proof is valid
|
||||
let pvk = prepare_verifying_key(verifying_key);
|
||||
//let pr: ArkProof<Curve> = (*proof).into();
|
||||
|
||||
// If in debug mode, we measure and later print time take to verify proof
|
||||
#[cfg(debug_assertions)]
|
||||
let now = Instant::now();
|
||||
|
||||
let verified = ark_verify_proof(&pvk, proof, &inputs)?;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
println!("verify took: {:.2?}", now.elapsed());
|
||||
|
||||
Ok(verified)
|
||||
|
|
|
@ -4,13 +4,15 @@ use ark_circom::WitnessCalculator;
|
|||
use ark_groth16::Proof as ArkProof;
|
||||
use ark_groth16::{ProvingKey, VerifyingKey};
|
||||
use ark_relations::r1cs::ConstraintMatrices;
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, Write};
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use std::default::Default;
|
||||
use std::io::Cursor;
|
||||
use std::io::{self, Result};
|
||||
use std::io::{self, Cursor, Read, Result, Write};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::circuit::{Curve, Fr, CIRCOM, TEST_RESOURCES_FOLDER, TEST_TREE_HEIGHT, VK, ZKEY};
|
||||
use crate::circuit::{
|
||||
circom_from_folder, circom_from_raw, vk_from_folder, vk_from_raw, zkey_from_folder,
|
||||
zkey_from_raw, Curve, Fr, TEST_RESOURCES_FOLDER, TEST_TREE_HEIGHT,
|
||||
};
|
||||
use crate::poseidon_tree::PoseidonTree;
|
||||
use crate::protocol::*;
|
||||
use crate::utils::*;
|
||||
|
@ -25,7 +27,6 @@ pub struct RLN<'a> {
|
|||
proving_key: Result<(ProvingKey<Curve>, ConstraintMatrices<Fr>)>,
|
||||
verification_key: Result<VerifyingKey<Curve>>,
|
||||
tree: PoseidonTree,
|
||||
resources_folder: String,
|
||||
}
|
||||
|
||||
impl RLN<'_> {
|
||||
|
@ -36,10 +37,40 @@ impl RLN<'_> {
|
|||
|
||||
let resources_folder = String::from_utf8(input).expect("Found invalid UTF-8");
|
||||
|
||||
let witness_calculator = CIRCOM(&resources_folder);
|
||||
let witness_calculator = circom_from_folder(&resources_folder);
|
||||
|
||||
let proving_key = ZKEY(&resources_folder);
|
||||
let verification_key = VK(&resources_folder);
|
||||
let proving_key = zkey_from_folder(&resources_folder);
|
||||
let verification_key = vk_from_folder(&resources_folder);
|
||||
|
||||
// We compute a default empty tree
|
||||
let tree = PoseidonTree::default(tree_height);
|
||||
|
||||
RLN {
|
||||
witness_calculator,
|
||||
proving_key,
|
||||
verification_key,
|
||||
tree,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_params<R: Read>(
|
||||
tree_height: usize,
|
||||
mut circom_data: R,
|
||||
mut zkey_data: R,
|
||||
mut vk_data: R,
|
||||
) -> RLN<'static> {
|
||||
// We read input
|
||||
let mut circom_vec: Vec<u8> = Vec::new();
|
||||
circom_data.read_to_end(&mut circom_vec).unwrap();
|
||||
let mut zkey_vec: Vec<u8> = Vec::new();
|
||||
zkey_data.read_to_end(&mut zkey_vec).unwrap();
|
||||
let mut vk_vec: Vec<u8> = Vec::new();
|
||||
vk_data.read_to_end(&mut vk_vec).unwrap();
|
||||
|
||||
let witness_calculator = circom_from_raw(circom_vec);
|
||||
|
||||
let proving_key = zkey_from_raw(&zkey_vec);
|
||||
let verification_key = vk_from_raw(&vk_vec, &zkey_vec);
|
||||
|
||||
// We compute a default empty tree
|
||||
let tree = PoseidonTree::default(tree_height);
|
||||
|
@ -49,7 +80,6 @@ impl RLN<'_> {
|
|||
proving_key,
|
||||
verification_key,
|
||||
tree,
|
||||
resources_folder,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue