seperate test runners

This commit is contained in:
kilic 2020-10-01 13:10:18 +03:00
parent 73da37a841
commit 72085d2e42
4 changed files with 215 additions and 180 deletions

View File

@ -10,12 +10,15 @@ crate-type = ["cdylib", "rlib"]
[features]
multicore = ["sapling-crypto/multicore", "bellman/multicore"]
wasm = ["sapling-crypto/wasm", "bellman/wasm", "bellman/nolog"]
bench = []
[dependencies]
rand = "0.4"
blake2 = "0.8.1"
sapling-crypto = { package = "sapling-crypto_ce", version = "0.1.3", default-features = false }
bellman = { package = "bellman_ce", version = "0.3.4", default-features = false }
# 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" }
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = { version = "0.1.1" }

196
src/circuit/bench.rs Normal file
View File

@ -0,0 +1,196 @@
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::*;
use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
use sapling_crypto::bellman::pairing::Engine;
use sapling_crypto::bellman::Circuit;
use sapling_crypto::circuit::test::TestConstraintSystem;
use std::error::Error;
use std::thread::sleep;
use std::time::{Duration, Instant};
pub struct BenchResult {
pub number_of_constaints: usize,
pub prover_key_size: usize,
pub prover_time: f64,
}
impl BenchResult {
pub fn new() -> BenchResult {
BenchResult {
number_of_constaints: 0,
prover_key_size: 0,
prover_time: 0f64,
}
}
pub fn print(&self) {
println!("number of constraints\n{}", self.number_of_constaints);
println!("prover key size\n{}", self.prover_key_size);
println!("prover time\n{}", self.prover_time);
}
}
// TODO make it composable: curve, poseidon, merkle
pub fn run_rln_bn_24() -> BenchResult {
use sapling_crypto::bellman::pairing::bn256::Bn256;
let poseidon_params = PoseidonParams::<Bn256>::default();
let rln_test = RLNTest::new(poseidon_params, 24);
rln_test.run()
}
pub fn run_rln_bn_32() -> BenchResult {
use sapling_crypto::bellman::pairing::bn256::Bn256;
let poseidon_params = PoseidonParams::<Bn256>::default();
let rln_test = RLNTest::new(poseidon_params, 32);
rln_test.run()
}
pub struct RLNTest<E>
where
E: Engine,
{
merkle_depth: usize,
poseidon_params: PoseidonParams<E>,
}
impl<E> RLNTest<E>
where
E: Engine,
{
pub fn new(poseidon_params: PoseidonParams<E>, merkle_depth: usize) -> RLNTest<E> {
// let cs = TestConstraintSystem::<E>::new();
RLNTest::<E> {
poseidon_params,
merkle_depth,
}
}
fn inputs(&self) -> RLNInputs<E> {
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let mut hasher = PoseidonHasher::new(self.poseidon_params.clone());
// Initialize empty merkle tree
let merkle_depth = self.merkle_depth;
let mut membership_tree = MerkleTree::empty(hasher.clone(), merkle_depth);
// A. setup an identity
let id_key = E::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 = E::Fr::rand(&mut rng);
let signal_hash = E::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]);
// compose the circuit
let inputs = RLNInputs::<E> {
share_x: Some(share_x),
share_y: Some(share_y),
epoch: Some(epoch),
nullifier: Some(nullifier),
root: Some(membership_tree.root()),
id_key: Some(id_key),
auth_path: auth_path.into_iter().map(|w| Some(w)).collect(),
};
inputs
}
fn empty_inputs(&self) -> RLNInputs<E> {
RLNInputs::<E> {
share_x: None,
share_y: None,
epoch: None,
nullifier: None,
root: None,
id_key: None,
auth_path: vec![None; self.merkle_depth],
}
}
pub fn run(&self) -> BenchResult {
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let hasher = PoseidonCircuit::new(self.poseidon_params.clone());
let inputs = self.inputs();
let circuit = RLNCircuit::<E> {
inputs: inputs.clone(),
hasher: hasher.clone(),
};
let mut result = BenchResult::new();
let mut cs = TestConstraintSystem::<E>::new();
{
let circuit = circuit.clone();
circuit.synthesize(&mut cs).unwrap();
let unsatisfied = cs.which_is_unsatisfied();
if unsatisfied.is_some() {
panic!("unsatisfied\n{}", unsatisfied.unwrap());
}
let unconstrained = cs.find_unconstrained();
if !unconstrained.is_empty() {
panic!("unconstrained\n{}", unconstrained);
}
assert!(cs.is_satisfied());
result.number_of_constaints = cs.num_constraints();
}
{
let parameters = {
let inputs = self.empty_inputs();
let circuit = RLNCircuit::<E> {
inputs,
hasher: hasher.clone(),
};
let parameters = generate_random_parameters(circuit, &mut rng).unwrap();
parameters
};
let mut v = vec![];
parameters.write(&mut v).unwrap();
result.prover_key_size = v.len();
let now = Instant::now();
let proof = create_random_proof(circuit, &parameters, &mut rng).unwrap();
result.prover_time = now.elapsed().as_millis() as f64 / 1000.0;
let verifing_key = prepare_verifying_key(&parameters.vk);
assert!(verify_proof(&verifing_key, &proof, &inputs.public_inputs()).unwrap());
}
result
}
}

View File

@ -1,3 +1,6 @@
mod polynomial;
pub mod poseidon;
pub mod rln;
#[cfg(any(test, feature = "bench"))]
pub mod bench;

View File

@ -49,7 +49,7 @@ impl<E> RLNInputs<E>
where
E: Engine,
{
fn public_inputs(&self) -> Vec<E::Fr> {
pub fn public_inputs(&self) -> Vec<E::Fr> {
vec![
self.root.unwrap(),
self.epoch.unwrap(),
@ -371,187 +371,20 @@ where
#[cfg(test)]
mod test {
use super::{RLNCircuit, RLNInputs};
use crate::circuit::poseidon::PoseidonCircuit;
use crate::merkle::MerkleTree;
use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams};
use rand::{Rand, SeedableRng, XorShiftRng};
// use sapling_crypto::bellman::groth16::{
// create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, Parameters,
// };
use sapling_crypto::bellman::groth16::*;
use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
use sapling_crypto::bellman::pairing::Engine;
use sapling_crypto::bellman::Circuit;
use sapling_crypto::circuit::test::TestConstraintSystem;
use std::thread::sleep;
use std::time::{Duration, Instant};
struct RLNTest<E>
where
E: Engine,
{
// cs: TestConstraintSystem<E>,
merkle_depth: usize,
poseidon_params: PoseidonParams<E>,
}
use super::RLNInputs;
use crate::circuit::bench;
impl<E> RLNTest<E>
where
E: Engine,
{
pub fn new(poseidon_params: PoseidonParams<E>, merkle_depth: usize) -> RLNTest<E> {
// let cs = TestConstraintSystem::<E>::new();
RLNTest::<E> {
poseidon_params,
merkle_depth,
}
}
fn inputs(&self) -> RLNInputs<E> {
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let mut hasher = PoseidonHasher::new(self.poseidon_params.clone());
// Initialize empty merkle tree
let merkle_depth = self.merkle_depth;
let mut membership_tree = MerkleTree::empty(hasher.clone(), merkle_depth);
// A. setup an identity
let id_key = E::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 = E::Fr::rand(&mut rng);
let signal_hash = E::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]);
// compose the circuit
let inputs = RLNInputs::<E> {
share_x: Some(share_x),
share_y: Some(share_y),
epoch: Some(epoch),
nullifier: Some(nullifier),
root: Some(membership_tree.root()),
id_key: Some(id_key),
auth_path: auth_path.into_iter().map(|w| Some(w)).collect(),
};
inputs
}
fn empty_inputs(&self) -> RLNInputs<E> {
RLNInputs::<E> {
share_x: None,
share_y: None,
epoch: None,
nullifier: None,
root: None,
id_key: None,
auth_path: vec![None; self.merkle_depth],
}
}
pub fn run(&self) {
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let hasher = PoseidonCircuit::new(self.poseidon_params.clone());
let inputs = self.inputs();
let circuit = RLNCircuit::<E> {
inputs: inputs.clone(),
hasher: hasher.clone(),
};
let mut cs = TestConstraintSystem::<E>::new();
{
let circuit = circuit.clone();
circuit.synthesize(&mut cs).unwrap();
let unsatisfied = cs.which_is_unsatisfied();
if unsatisfied.is_some() {
panic!("unsatisfied\n{}", unsatisfied.unwrap());
}
let unconstrained = cs.find_unconstrained();
if !unconstrained.is_empty() {
panic!("unconstrained\n{}", unconstrained);
}
assert!(cs.is_satisfied());
println!("number of constaints: {}", cs.num_constraints());
}
{
let parameters = {
let inputs = self.empty_inputs();
let circuit = RLNCircuit::<E> {
inputs,
hasher: hasher.clone(),
};
let parameters = generate_random_parameters(circuit, &mut rng).unwrap();
parameters
};
// let mut key_size = 0;
// let point_size = (((E::Fr::NUM_BITS / 64) + 1) * 8 * 2) as usize;
// key_size += parameters.a.len() * point_size;
// key_size += parameters.l.len() * point_size;
// key_size += parameters.h.len() * point_size;
// key_size += parameters.b_g1.len() * point_size;
// key_size += parameters.b_g2.len() * point_size * 2;
// println!("prover key size in bytes: {}", key_size);
let mut v = vec![];
parameters.write(&mut v).unwrap();
println!("circuit parameter size in bytes: {}", v.len());
let now = Instant::now();
let proof = create_random_proof(circuit, &parameters, &mut rng).unwrap();
println!("prover time: {}", now.elapsed().as_millis() as f64 / 1000.0);
let verifing_key = prepare_verifying_key(&parameters.vk);
assert!(verify_proof(&verifing_key, &proof, &inputs.public_inputs()).unwrap());
}
}
#[test]
fn test_rln_bn_24() {
let result = bench::run_rln_bn_24();
result.print();
}
#[test]
fn test_rln_24() {
use sapling_crypto::bellman::pairing::bn256::Bn256;
let poseidon_params = PoseidonParams::<Bn256>::default();
let rln_test = RLNTest::new(poseidon_params, 24);
rln_test.run();
}
#[test]
fn test_rln_32() {
use sapling_crypto::bellman::pairing::bn256::Bn256;
let poseidon_params = PoseidonParams::<Bn256>::default();
let rln_test = RLNTest::new(poseidon_params, 32);
rln_test.run();
fn test_rln_bn_32() {
let result = bench::run_rln_bn_32();
result.print();
}
#[test]