From cbc8e7579a11c81249d649f51e0f23357e5939cf Mon Sep 17 00:00:00 2001 From: kilic Date: Wed, 28 Oct 2020 19:13:32 +0300 Subject: [PATCH] add js verifier key exporter --- Cargo.toml | 21 ++++--- src/wasm/wasm.rs | 159 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 157 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3b915d3..02b7dcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,16 +15,23 @@ bench = [] [dependencies] rand = "0.4" blake2 = "0.8.1" -# sapling-crypto = { package = "sapling-crypto_ce", version = "0.1.3", default-features = false } -sapling-crypto = {package = "sapling-crypto_ce", path = "../sapling-crypto" } -# bellman = { package = "bellman_ce", version = "0.3.4", default-features = false } -bellman = {package = "bellman_ce", path = "../bellman" } +sapling-crypto = { package = "sapling-crypto_ce", version = "0.1.3", default-features = false } +# sapling-crypto = {package = "sapling-crypto_ce", path = "../sapling-crypto", default-features = false } +bellman = { package = "bellman_ce", version = "0.3.4", default-features = false } +# bellman = {package = "bellman_ce", path = "../bellman", default-features = false } [target.'cfg(target_arch = "wasm32")'.dependencies] +hex = "0.4" console_error_panic_hook = { version = "0.1.1" } -wasm-bindgen = "0.2.63" -wee_alloc = "0.4.5" +wasm-bindgen = "=0.2.60" +# wee_alloc = "0.4.5" web-sys = {version = "0.3", features = ["console", "Performance", "Window"]} +js-sys = "0.3.37" [target.'cfg(target_arch = "wasm32")'.dev-dependencies] -wasm-bindgen-test = "0.3" \ No newline at end of file +wasm-bindgen-test = "0.3" + +[profile.release] +# Tell `rustc` to optimize for small code size. +opt-level = 3 + diff --git a/src/wasm/wasm.rs b/src/wasm/wasm.rs index e444fbb..5fae648 100644 --- a/src/wasm/wasm.rs +++ b/src/wasm/wasm.rs @@ -2,31 +2,154 @@ use super::utils::set_panic_hook; use crate::circuit::poseidon::PoseidonCircuit; use crate::circuit::rln::{RLNCircuit, RLNInputs}; use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams}; -use sapling_crypto::bellman::groth16::{create_proof, prepare_verifying_key, verify_proof}; -use sapling_crypto::bellman::groth16::{create_random_proof, Parameters, Proof}; -use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr}; -use sapling_crypto::bellman::pairing::Engine; -use sapling_crypto::bellman::{Circuit, ConstraintSystem, SynthesisError}; +use bellman::groth16::{create_proof, prepare_verifying_key, verify_proof}; +use bellman::groth16::{create_random_proof, Parameters, Proof}; +use bellman::pairing::bn256::{Bn256, Fr}; +use bellman::pairing::Engine; +use bellman::{Circuit, ConstraintSystem, SynthesisError}; use std::io::{self, Error, ErrorKind, Read, Write}; use wasm_bindgen::prelude::*; -#[global_allocator] -static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; +use crate::merkle::MerkleTree; + +use bellman::groth16::generate_random_parameters; +use bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr}; +use bellman::pairing::CurveAffine; +use rand::{Rand, SeedableRng, XorShiftRng}; #[wasm_bindgen] -struct RLNWasm { +pub struct RLNWasm { circuit_parameters: Parameters, circuit_hasher: PoseidonCircuit, merkle_depth: usize, } +#[wasm_bindgen] +pub struct G1Hex { + x: String, + y: String, +} + +#[wasm_bindgen] +pub struct G2Hex { + x_c0: String, + x_c1: String, + y_c0: String, + y_c1: String, +} + +impl G1Hex { + pub fn x(&self) -> String { + self.x.clone() + } + + pub fn y(&self) -> String { + self.y.clone() + } +} + +impl G2Hex { + pub fn x_c0(&self) -> String { + self.x_c0.clone() + } + + pub fn x_c1(&self) -> String { + self.x_c1.clone() + } + + pub fn y_c0(&self) -> String { + self.y_c0.clone() + } + + pub fn y_c1(&self) -> String { + self.y_c1.clone() + } +} + +#[wasm_bindgen] +pub struct VerifierKey { + alpha_1: G1Hex, + beta_2: G2Hex, + gamma_2: G2Hex, + delta_2: G2Hex, + ic_array: Array, +} + +use sapling_crypto::bellman::pairing::bn256::{G1Affine, G2Affine}; + +use js_sys::Array; + +impl VerifierKey { + pub fn some() -> Array { + let js_array: Array = Array::new(); + + js_array.push(&wasm_bindgen::JsValue::from(String::from("xxx"))); + js_array.push(&wasm_bindgen::JsValue::from(String::from("yyy"))); + js_array + } + + pub fn new(circuit_parameters: Parameters) -> VerifierKey { + let vk = circuit_parameters.vk; + let ic_array: Array = Array::new(); + for e_ic in vk.ic.iter() { + ic_array.push(&wasm_bindgen::JsValue::from(Self::g1_to_js(e_ic.clone()))); + } + VerifierKey { + alpha_1: Self::g1_to_js(vk.alpha_g1), + beta_2: Self::g2_to_js(vk.beta_g2), + gamma_2: Self::g2_to_js(vk.gamma_g2), + delta_2: Self::g2_to_js(vk.delta_g2), + ic_array, + } + } + + fn g1_to_js(point: G1Affine) -> G1Hex { + let mut buf_x: Vec = vec![]; + let mut buf_y: Vec = vec![]; + let point_xy = point.into_xy_unchecked(); + point_xy.0.into_repr().write_be(&mut buf_x).unwrap(); + let x = hex::encode(buf_x); + point_xy.1.into_repr().write_be(&mut buf_y).unwrap(); + let y = hex::encode(buf_y); + G1Hex { x, y } + } + + fn g2_to_js(point: G2Affine) -> G2Hex { + let mut buf_x_c0: Vec = vec![]; + let mut buf_x_c1: Vec = vec![]; + let mut buf_y_c0: Vec = vec![]; + let mut buf_y_c1: Vec = vec![]; + + let point_xy = point.into_xy_unchecked(); + + point_xy.0.c0.into_repr().write_be(&mut buf_x_c0).unwrap(); + let x_c0 = hex::encode(buf_x_c0); + + point_xy.0.c1.into_repr().write_be(&mut buf_x_c1).unwrap(); + let x_c1 = hex::encode(buf_x_c1); + + point_xy.1.c0.into_repr().write_be(&mut buf_y_c0).unwrap(); + let y_c0 = hex::encode(buf_y_c0); + + point_xy.1.c1.into_repr().write_be(&mut buf_y_c1).unwrap(); + let y_c1 = hex::encode(buf_y_c1); + + G2Hex { + x_c0, + x_c1, + y_c0, + y_c1, + } + } +} + #[wasm_bindgen] impl RLNWasm { #[wasm_bindgen] pub fn new(merkle_depth: usize, raw_circuit_parameters: &[u8]) -> RLNWasm { set_panic_hook(); let circuit_parameters = Parameters::::read(raw_circuit_parameters, true).unwrap(); - let poseidon_params = PoseidonParams::::default(); + let poseidon_params = PoseidonParams::::new(8, 55, 3, None, None, None); let circuit_hasher = PoseidonCircuit::new(poseidon_params.clone()); RLNWasm { circuit_parameters, @@ -35,6 +158,10 @@ impl RLNWasm { } } + pub fn export_verifier_key(&self) -> VerifierKey { + VerifierKey::new(self.circuit_parameters.clone()) + } + #[wasm_bindgen] pub fn generate_proof(&self, input: &[u8]) -> Result, JsValue> { use rand::chacha::ChaChaRng; @@ -68,20 +195,20 @@ impl RLNWasm { #[cfg(test)] mod test { + use wasm_bindgen_test::*; + use crate::circuit::poseidon::PoseidonCircuit; use crate::circuit::rln::{RLNCircuit, RLNInputs}; use crate::merkle::MerkleTree; use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams}; + use bellman::groth16::{generate_random_parameters, Parameters, Proof}; + use bellman::pairing::bn256::{Bn256, Fr}; + use bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr}; use rand::{Rand, SeedableRng, XorShiftRng}; - use sapling_crypto::bellman::groth16::{generate_random_parameters, Parameters, Proof}; - use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr}; - use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr}; - - use wasm_bindgen_test::*; fn gen_circuit_parameters(merkle_depth: usize) -> Vec { let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - let poseidon_params = PoseidonParams::::default(); + let poseidon_params = PoseidonParams::::new(8, 55, 3, None, None, None); let inputs = RLNInputs::::empty(merkle_depth); let circuit = RLNCircuit:: { inputs, @@ -95,7 +222,7 @@ mod test { fn gen_valid_inputs(merkle_depth: usize) -> RLNInputs { let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]); - let poseidon_params = PoseidonParams::::default(); + let poseidon_params = PoseidonParams::::new(8, 55, 3, None, None, None); let mut hasher = PoseidonHasher::new(poseidon_params.clone()); let mut membership_tree = MerkleTree::empty(hasher.clone(), merkle_depth);