Skip to content

Commit

Permalink
calling zerokit from js
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-ramos committed Sep 2, 2022
1 parent 7acbde2 commit cde40ba
Show file tree
Hide file tree
Showing 19 changed files with 13,809 additions and 101 deletions.
31 changes: 24 additions & 7 deletions rln/Cargo.toml
Expand Up @@ -6,18 +6,24 @@ edition = "2021"
[lib]
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-ec = { version = "0.3.0", default-features = false }
ark-ff = { version = "0.3.0", default-features = false, features = [ "asm"] }
ark-std = { version = "0.3.0", default-features = false }
ark-bn254 = { version = "0.3.0" }
ark-groth16 = { git = "https://github.com/arkworks-rs/groth16", rev = "765817f", features = ["parallel"] }
ark-groth16 = { git = "https://github.com/arkworks-rs/groth16", rev = "765817f", default-features = false }
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/vacp2p/ark-circom", branch = "wasm", features = ["circom-2"] }
getrandom = { version = "0.2.7", default-features = false, features = ["js"] }

# WASM
wasmer = { version = "2.3", default-features = false, features = ["js", "std"] }
wasm-bindgen = "0.2.63"
serde-wasm-bindgen = "0.4"

# error handling
color-eyre = "0.5"
Expand All @@ -26,7 +32,7 @@ thiserror = "1.0.0"
# utilities
cfg-if = "1.0"
hex-literal = "0.3"
num-bigint = { version = "0.4", default-features = false, features = ["rand"] }
num-bigint = { version = "0.4", default-features = false, features = ["rand", "serde"] }
num-traits = "0.2.15"
once_cell = "1.8"
rand = "0.8"
Expand All @@ -35,6 +41,17 @@ tiny-keccak = "2.0.2"
# serialization
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
serde_json = "1.0.48"
base64 = "0.13.0"
js-sys = "0.3.59"
console_error_panic_hook = "0.1.7"


[profile.release]
debug = true

[features]
fullmerkletree = []

[dependencies.web-sys]
version = "0.3"
features = [ "console" ]
23 changes: 9 additions & 14 deletions rln/src/circuit.rs
Expand Up @@ -8,15 +8,14 @@ use ark_circom::{read_zkey, WitnessCalculator};
use ark_groth16::{ProvingKey, VerifyingKey};
use ark_relations::r1cs::ConstraintMatrices;
use num_bigint::BigUint;
use once_cell::sync::OnceCell;
use serde_json::Value;
use std::fs::File;
use std::io::{Cursor, Error, ErrorKind, Read, Result};
use std::path::Path;
use std::str::FromStr;
use std::sync::Mutex;
use wasmer::{Module, Store};

extern crate base64;
extern crate web_sys;
const ZKEY_FILENAME: &str = "rln_final.zkey";
const VK_FILENAME: &str = "verifying_key.json";
const WASM_FILENAME: &str = "rln.wasm";
Expand Down Expand Up @@ -109,8 +108,6 @@ pub fn vk_from_folder(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}");
Expand All @@ -124,18 +121,16 @@ fn read_wasm(resources_folder: &str) -> Vec<u8> {
}

// 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(|| {
let store = Store::default();
let module = Module::from_binary(&store, &wasm_buffer).expect("wasm should be valid");
let result =
WitnessCalculator::from_module(module).expect("Failed to create witness calculator");
Mutex::new(result)
})
pub fn circom_from_raw(wasm_buffer: Vec<u8>) -> WitnessCalculator {
let store = Store::default();
let module = Module::from_binary(&store, &wasm_buffer).expect("wasm should be valid");
let result =
WitnessCalculator::from_module(module).expect("Failed to create witness calculator");
result
}

// Initializes the witness calculator
pub fn circom_from_folder(resources_folder: &str) -> &'static Mutex<WitnessCalculator> {
pub fn circom_from_folder(resources_folder: &str) -> WitnessCalculator {
// We read the wasm file
let wasm_buffer = read_wasm(resources_folder);
circom_from_raw(wasm_buffer)
Expand Down
13 changes: 9 additions & 4 deletions rln/src/ffi.rs
Expand Up @@ -42,8 +42,8 @@ impl<'a> From<&Buffer> for &'a [u8] {
#[no_mangle]
pub extern "C" fn new(tree_height: usize, input_buffer: *const Buffer, ctx: *mut *mut RLN) -> bool {
let input_data = <&[u8]>::from(unsafe { &*input_buffer });
let rln = RLN::new(tree_height, input_data);
unsafe { *ctx = Box::into_raw(Box::new(rln)) };
//let rln = RLN::new(tree_height, input_data);
//unsafe { *ctx = Box::into_raw(Box::new(rln)) };
true
}

Expand All @@ -59,8 +59,8 @@ pub extern "C" fn new_with_params(
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)) };
//let rln = RLN::new_with_params(tree_height, circom_data, zkey_data, vk_data);
//unsafe { *ctx = Box::into_raw(Box::new(rln)) };
true
}

Expand Down Expand Up @@ -190,6 +190,7 @@ pub extern "C" fn generate_rln_proof(
let input_data = <&[u8]>::from(unsafe { &*input_buffer });
let mut output_data: Vec<u8> = Vec::new();

/*
if rln.generate_rln_proof(input_data, &mut output_data).is_ok() {
unsafe { *output_buffer = Buffer::from(&output_data[..]) };
std::mem::forget(output_data);
Expand All @@ -198,6 +199,8 @@ pub extern "C" fn generate_rln_proof(
std::mem::forget(output_data);
false
}
*/
true
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
Expand Down Expand Up @@ -259,6 +262,7 @@ pub extern "C" fn hash(
}
}

/*
#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -784,3 +788,4 @@ mod test {
assert_eq!(hash1, hash2);
}
}
*/
9 changes: 5 additions & 4 deletions rln/src/lib.rs
Expand Up @@ -2,6 +2,7 @@

pub mod circuit;
pub mod ffi;
pub mod wasm;
pub mod merkle_tree;
pub mod poseidon_constants;
pub mod poseidon_hash;
Expand Down Expand Up @@ -332,7 +333,7 @@ mod test {
// 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);
let mut builder = circom_from_folder(TEST_RESOURCES_FOLDER);

// We compute witness from the json input example
let mut witness_json: &str = "";
Expand All @@ -345,7 +346,7 @@ mod test {
witness_json = WITNESS_JSON_20;
}

let rln_witness = rln_witness_from_json(witness_json);
let rln_witness = rln_witness_from_json(&mut witness_json);

// Let's generate a zkSNARK proof
let proof = generate_proof(builder, &proving_key, &rln_witness).unwrap();
Expand Down Expand Up @@ -389,12 +390,12 @@ mod test {
);

// We generate all relevant keys
let proving_key = zkey_from_folder(TEST_RESOURCES_FOLDER).unwrap();
let proving_key = zkey_from_folder(&mut 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();
let proof = generate_proof(&mut builder, &proving_key, &rln_witness).unwrap();

let proof_values = proof_values_from_witness(&rln_witness);

Expand Down
109 changes: 100 additions & 9 deletions rln/src/protocol.rs
Expand Up @@ -11,7 +11,6 @@ use ark_std::{rand::thread_rng, UniformRand};
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;
Expand Down Expand Up @@ -121,12 +120,9 @@ pub fn proof_inputs_to_rln_witness(
let signal_len = u64::from_le_bytes(serialized[all_read..all_read + 8].try_into().unwrap());
all_read += 8;

let signal: Vec<u8> =
serialized[all_read..all_read + usize::try_from(signal_len).unwrap()].to_vec();
let signal: Vec<u8> = serialized[all_read..all_read + (signal_len as usize)].to_vec();

let merkle_proof = tree
.proof(usize::try_from(id_index).unwrap())
.expect("proof should exist");
let merkle_proof = tree.proof(id_index as usize).expect("proof should exist");
let path_elements = merkle_proof.get_path_elements();
let identity_path_index = merkle_proof.get_path_index();

Expand Down Expand Up @@ -374,13 +370,81 @@ pub enum ProofError {
SynthesisError(#[from] SynthesisError),
}

fn calculate_witness_element<E: ark_ec::PairingEngine>(
witness: Vec<BigInt>,
sanity_check: bool,
) -> Result<Vec<E::Fr>> {
use ark_ff::{FpParameters, PrimeField};
let modulus = <<E::Fr as PrimeField>::Params as FpParameters>::MODULUS;

// convert it to field elements
use num_traits::Signed;
let witness = witness
.into_iter()
.map(|w| {
let w = if w.sign() == num_bigint::Sign::Minus {
// Need to negate the witness element if negative
modulus.into() - w.abs().to_biguint().unwrap()
} else {
w.to_biguint().unwrap()
};
E::Fr::from(w)
})
.collect::<Vec<_>>();

Ok(witness)
}

pub fn generate_proof_with_witness(
witness: Vec<BigInt>,
proving_key: &(ProvingKey<Curve>, ConstraintMatrices<Fr>),
) /*-> Result<ArkProof<Curve>, ProofError>*/
{
// If in debug mode, we measure and later print time take to compute witness
// #[cfg(debug_assertions)]
//let now = Instant::now();

let full_assignment = calculate_witness_element::<Curve>(witness, false)
.map_err(ProofError::WitnessError)
.unwrap();

// #[cfg(debug_assertions)]
//println!("witness generation took: {:.2?}", now.elapsed());

// Random Values
let mut rng = thread_rng();
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();

// TODO: this function fails
let proof = create_proof_with_reduction_and_matrices::<_, CircomReduction>(
&proving_key.0,
r,
s,
&proving_key.1,
proving_key.1.num_instance_variables,
proving_key.1.num_constraints,
full_assignment.as_slice(),
)
.unwrap();

// #[cfg(debug_assertions)]
// println!("proof generation took: {:.2?}", now.elapsed());

// Ok(proof)
}

/// Generates a RLN proof
///
/// # Errors
///
/// Returns a [`ProofError`] if proving fails.
pub fn generate_proof(
witness_calculator: &Mutex<WitnessCalculator>,
witness_calculator: &mut WitnessCalculator,
proving_key: &(ProvingKey<Curve>, ConstraintMatrices<Fr>),
rln_witness: &RLNWitnessInput,
) -> Result<ArkProof<Curve>, ProofError> {
Expand Down Expand Up @@ -421,8 +485,6 @@ pub fn generate_proof(
let now = Instant::now();

let full_assignment = witness_calculator
.lock()
.expect("witness_calculator mutex should not get poisoned")
.calculate_witness_element::<Curve, _>(inputs, false)
.map_err(ProofError::WitnessError)?;

Expand Down Expand Up @@ -490,3 +552,32 @@ pub fn verify_proof(

Ok(verified)
}

/// Get CIRCOM JSON inputs
///
/// Returns a JSON object containing the inputs necessary to calculate
/// the witness with CIRCOM on javascript
pub fn get_json_inputs<'a>(rln_witness: &RLNWitnessInput) -> serde_json::Value {
let mut path_elements = Vec::new();
rln_witness
.path_elements
.iter()
.for_each(|v| path_elements.push(to_bigint(v).to_str_radix(10)));

let mut identity_path_index = Vec::new();
rln_witness
.identity_path_index
.iter()
.for_each(|v| identity_path_index.push(BigInt::from(*v).to_str_radix(10)));

let inputs = serde_json::json!({
"identity_secret": to_bigint(&rln_witness.identity_secret).to_str_radix(10),
"path_elements": path_elements,
"identity_path_index": identity_path_index,
"x": to_bigint(&rln_witness.x).to_str_radix(10),
"epoch": format!("0x{:064x}", to_bigint(&rln_witness.epoch)),
"rln_identifier": to_bigint(&rln_witness.rln_identifier).to_str_radix(10),
});

return inputs;
}

0 comments on commit cde40ba

Please sign in to comment.