wip, wasm effort

This commit is contained in:
kilic
2020-06-04 20:59:02 +03:00
parent 945b23bf70
commit e6e563413c
14 changed files with 5785 additions and 8 deletions

3
.gitignore vendored
View File

@@ -1,2 +1,5 @@
/target
/pkg
node_modules
*.key
Cargo.lock

View File

@@ -1,10 +1,22 @@
[package]
name = "rln"
version = "0.1.0"
authors = ["Onur Kılıç <onurkilic@itu.edu.tr>"]
authors = ["Onur Kılıç <kiliconu@itu.edu.tr>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
rand = "0.4"
blake2 = "0.8.1"
sapling-crypto = { package = "sapling-crypto_ce", version = "0.1.2" }
hex = "0.4.2"
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = { version = "0.1.1" }
wasm-bindgen = "0.2"
wee_alloc = "0.4.5"
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.2"

10
example/www/index.html Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>rln prover example</title>
</head>
<body>
<script src="./index.js"></script>
</body>
</html>

16
example/www/index.js Normal file
View File

@@ -0,0 +1,16 @@
// import key from 'binary-loader!./verifier.key';
// var hexdata = Buffer.from(key, 'ascii').toString('hex');
const js = import('../../pkg/rln.js');
js.then((js) => {
bufi = Buffer.alloc(64, 1);
buf0 = Buffer.alloc(32, 0);
// console.log(buf);
try {
let result = js.RLNWasm.generate_proof(bufi, buf0);
console.log(result);
console.log(buf0[0]);
} catch (err) {
console.log('LOGS ERROR');
console.log(err);
}
});

5475
example/www/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

13
example/www/package.json Normal file
View File

@@ -0,0 +1,13 @@
{
"scripts": {
"serve": "webpack-dev-server"
},
"devDependencies": {
"binary-loader": "0.0.1",
"file-loader": "^6.0.0",
"raw-loader": "^4.0.1",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
}
}

View File

@@ -0,0 +1,25 @@
const path = require('path');
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
},
// module: {
// rules: [{ test: /\.key$/, use: 'raw-loader' }],
// },
// module: {
// rules: [
// {
// test: /\.(key)$/i,
// use: [
// {
// loader: 'file-loader',
// },
// ],
// },
// ],
// },
mode: 'development',
};

View File

@@ -0,0 +1,44 @@
use hex;
use sapling_crypto::bellman::pairing::Engine;
use std::fs::File;
use std::io::prelude::*;
fn main() {
use sapling_crypto::bellman::pairing::bn256::Bn256;
let merkle_depth = 32usize;
export_test_keys::<Bn256>(merkle_depth);
}
fn export_test_keys<E: Engine>(merkle_depth: usize) {
// use rand::{Rand, SeedableRng, XorShiftRng};
// use rln::circuit::poseidon::PoseidonCircuit;
// use rln::circuit::rln::{RLNCircuit, RLNInputs};
// use rln::poseidon::PoseidonParams;
use sapling_crypto::bellman::groth16::{generate_random_parameters, Parameters};
// let poseidon_params = PoseidonParams::<E>::default();
// let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
// let hasher = PoseidonCircuit::new(poseidon_params.clone());
// let circuit = RLNCircuit::<E> {
// inputs: RLNInputs::<E>::empty(merkle_depth),
// hasher: hasher.clone(),
// };
// let parameters = generate_random_parameters(circuit, &mut rng).unwrap();
// let mut file_vk = File::create("verifier.key").unwrap();
// let vk = parameters.vk.clone();
// let s = "1122";
// let r = hex::decode(s);
// println!("{:?}", r);
let mut s: Vec<u8> = vec![0; 63];
// vk.write(&mut s).unwrap();
// println!("{:x?}", s);
// println!("{}", s.len());
// println!("{}", hex::encode(&s));
// file_vk.write_all(&s).unwrap();
let parameters2 = Parameters::<E>::read(&mut s.as_slice(), true).unwrap();
println!("{:?}", parameters2.h);
println!("xxx");
}

View File

@@ -1,3 +1,3 @@
mod polynomial;
mod poseidon;
mod rln;
pub mod poseidon;
pub mod rln;

View File

@@ -1,6 +1,9 @@
#![allow(dead_code)]
#![allow(unused_imports)]
mod circuit;
mod merkle;
mod poseidon;
pub mod circuit;
pub mod merkle;
pub mod poseidon;
#[cfg(target_arch = "wasm32")]
mod wasm;

View File

@@ -72,8 +72,7 @@ where
}
}
};
let x = self.hasher.hash(vec![new]);
self.nodes.insert((d, leaf_index), x);
self.recalculate_from(leaf_index);
}

2
src/wasm/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
mod utils;
mod wasm;

10
src/wasm/utils.rs Normal file
View File

@@ -0,0 +1,10 @@
pub fn set_panic_hook() {
// When the `console_error_panic_hook` feature is enabled, we can call the
// `set_panic_hook` function at least once during initialization, and then
// we will get better error messages if our code ever panics.
//
// For more details see
// https://github.com/rustwasm/console_error_panic_hook#readme
// #[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
}

165
src/wasm/wasm.rs Normal file
View File

@@ -0,0 +1,165 @@
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 std::io::{self, Error, ErrorKind, Read, Write};
use wasm_bindgen::prelude::*;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
struct RLNWasm {
circuit_parameters: Parameters<Bn256>,
circuit_hasher: PoseidonCircuit<Bn256>,
merkle_depth: usize,
}
#[wasm_bindgen]
impl RLNWasm {
#[wasm_bindgen]
pub fn new(merkle_depth: usize, raw_circuit_parameters: &[u8]) -> RLNWasm {
set_panic_hook();
let circuit_parameters = Parameters::<Bn256>::read(raw_circuit_parameters, true).unwrap();
let poseidon_params = PoseidonParams::<Bn256>::default();
let circuit_hasher = PoseidonCircuit::new(poseidon_params.clone());
RLNWasm {
circuit_parameters,
circuit_hasher,
merkle_depth,
}
}
#[wasm_bindgen]
pub fn generate_proof(&self, input: &[u8]) -> Result<Vec<u8>, JsValue> {
use rand::chacha::ChaChaRng;
use rand::SeedableRng;
let mut rng = ChaChaRng::new_unseeded();
let inputs = RLNInputs::<Bn256>::read(input).expect("failed to read inputs");
assert_eq!(self.merkle_depth, inputs.merkle_depth());
let circuit = RLNCircuit {
inputs: inputs.clone(),
hasher: self.circuit_hasher.clone(),
};
let proof = create_random_proof(circuit, &self.circuit_parameters, &mut rng).expect("failed to create proof");
let mut output: Vec<u8> = Vec::new();
proof.write(&mut output).expect("failed to write proof");
Ok(output)
}
#[wasm_bindgen]
pub fn verify(&self, raw_proof: &[u8], raw_public_inputs: &[u8]) -> bool {
let proof = Proof::read(raw_proof).unwrap();
let public_inputs =
RLNInputs::<Bn256>::read_public_inputs(raw_public_inputs).expect("failed to read public inputs");
let verifing_key = prepare_verifying_key(&self.circuit_parameters.vk);
let success = verify_proof(&verifing_key, &proof, &public_inputs).expect("failed to verify proof");
success
}
}
#[cfg(test)]
mod test {
use crate::circuit::poseidon::PoseidonCircuit;
use crate::circuit::rln::{RLNCircuit, RLNInputs};
use crate::merkle::MerkleTree;
use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams};
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<u8> {
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let poseidon_params = PoseidonParams::<Bn256>::default();
let inputs = RLNInputs::<Bn256>::empty(merkle_depth);
let circuit = RLNCircuit::<Bn256> {
inputs,
hasher: PoseidonCircuit::new(poseidon_params.clone()),
};
let parameters = generate_random_parameters(circuit, &mut rng).unwrap();
let mut writer: Vec<u8> = Vec::new();
parameters.write(&mut writer);
writer
}
#[wasm_bindgen_test]
fn test_rln_wasm() {
let merkle_depth = 32usize;
let circuit_parameters = gen_circuit_parameters(merkle_depth);
//
// prepare inputs
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let poseidon_params = PoseidonParams::<Bn256>::default();
let mut hasher = PoseidonHasher::new(poseidon_params.clone());
let mut membership_tree = MerkleTree::empty(hasher.clone(), merkle_depth);
// A. setup an identity
let id_key = Fr::rand(&mut rng);
let id_comm = hasher.hash(vec![id_key.clone()]);
// B. insert to the membership tree
let id_index = 6; // any number below 2^depth will work
membership_tree.update(id_index, id_comm);
// C.1 get membership witness
let auth_path = membership_tree.witness(id_index);
assert!(membership_tree.check_inclusion(auth_path.clone(), id_index, id_key.clone()));
// C.2 prepare sss
// get current epoch
let epoch = Fr::rand(&mut rng);
let signal_hash = Fr::rand(&mut rng);
// evaluation point is the signal_hash
let share_x = signal_hash.clone();
// calculate current line equation
let a_0 = id_key.clone();
let a_1 = hasher.hash(vec![a_0, epoch]);
// evaluate line equation
let mut share_y = a_1.clone();
share_y.mul_assign(&share_x);
share_y.add_assign(&a_0);
// calculate nullfier
let nullifier = hasher.hash(vec![a_1]);
let root = membership_tree.root();
//
// serialize input
let mut writer: Vec<u8> = Vec::new();
share_x.into_repr().write_le(&mut writer).unwrap();
share_y.into_repr().write_le(&mut writer).unwrap();
epoch.into_repr().write_le(&mut writer).unwrap();
nullifier.into_repr().write_le(&mut writer).unwrap();
root.into_repr().write_le(&mut writer).unwrap();
id_key.into_repr().write_le(&mut writer).unwrap();
for (e, _) in auth_path.iter() {
e.into_repr().write_le(&mut writer).unwrap();
}
let raw_circuit_parameters = writer.as_slice();
//
// call wasm
use super::RLNWasm;
// let rlnWasm = RLNWasm::new(merkle_depth, raw_circuit_parameters);
}
}