Skip to content

Commit

Permalink
remove dylib and wasm, impl graph
Browse files Browse the repository at this point in the history
  • Loading branch information
philsippl committed Nov 10, 2023
1 parent 62a3b3b commit 95cf9a2
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 136 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ members = ["crates/*"]
[features]
default = []
bench = ["criterion", "proptest"]
dylib = ["wasmer/dylib", "wasmer-engine-dylib", "wasmer-compiler-cranelift"]
depth_16 = ["semaphore-depth-config/depth_16", "semaphore-depth-macros/depth_16"]
depth_20 = ["semaphore-depth-config/depth_20", "semaphore-depth-macros/depth_20"]
depth_30 = ["semaphore-depth-config/depth_30", "semaphore-depth-macros/depth_30"]
Expand Down Expand Up @@ -47,7 +46,7 @@ once_cell = "1.8"
proptest = { version = "1.0", optional = true }
rand = "0.8.4"
rayon = "1.5.1"
ruint = { version = "1.2.0", features = ["serde", "num-bigint", "ark-ff"] }
ruint = { version = "1.10.1", features = ["serde", "num-bigint", "ark-ff"] }
semaphore-depth-config = { path = "crates/semaphore-depth-config" }
serde = "1.0"
sha2 = "0.10.1"
Expand All @@ -58,6 +57,7 @@ semaphore-depth-macros = { path = "crates/semaphore-depth-macros" }
zeroize = "1.6.0"
mmap-rs = "0.5.0"
bincode = "1.3.3"
witness = { git = "https://github.com/philsippl/circom-witness-rs", rev="57d8b62" }

# Use the same `ethers-core` version as ark-circom
# TODO: Remove
Expand Down
55 changes: 7 additions & 48 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn build_circuit(depth: usize) -> Result<()> {
}

let depth_str = &depth.to_string();
let extensions = ["wasm", "zkey"];
let extensions = ["zkey"];

let depth_subfolder = base_path.join(depth_str);
if !Path::new(&depth_subfolder).exists() {
Expand All @@ -67,10 +67,12 @@ fn build_circuit(depth: usize) -> Result<()> {

// Compute absolute paths
let zkey_file = absolute(semaphore_file_path("semaphore.zkey", depth))?;
let wasm_file = absolute(semaphore_file_path("semaphore.wasm", depth))?;
let graph_file = absolute(Path::new("graphs")
.join(depth.to_string())
.join("graph.bin"))?;

assert!(zkey_file.exists());
assert!(wasm_file.exists());
assert!(graph_file.exists());

// Export generated paths
println!(
Expand All @@ -79,60 +81,17 @@ fn build_circuit(depth: usize) -> Result<()> {
zkey_file.display()
);
println!(
"cargo:rustc-env=BUILD_RS_WASM_FILE_{}={}",
"cargo:rustc-env=BUILD_RS_GRAPH_FILE_{}={}",
depth,
wasm_file.display()
graph_file.display()
);

Ok(())
}

#[cfg(feature = "dylib")]
fn build_dylib(depth: usize) -> Result<()> {
use color_eyre::eyre::eyre;
use enumset::{enum_set, EnumSet};
use std::{env, str::FromStr};
use wasmer::{Module, Store, Target, Triple};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_dylib::Dylib;

let wasm_file = absolute(semaphore_file_path("semaphore.wasm", depth))?;
assert!(wasm_file.exists());

let out_dir = env::var("OUT_DIR")?;
let out_dir = Path::new(&out_dir).to_path_buf();
let dylib_file = out_dir.join(format!("semaphore_{depth}.dylib"));
println!(
"cargo:rustc-env=CIRCUIT_WASM_DYLIB_{}={}",
depth,
dylib_file.display()
);

if dylib_file.exists() {
return Ok(());
}

// Create a WASM engine for the target that can compile
let triple = Triple::from_str(&env::var("TARGET")?).map_err(|e| eyre!(e))?;
let cpu_features = enum_set!();
let target = Target::new(triple, cpu_features);
let engine = Dylib::new(Cranelift::default()).target(target).engine();

// Compile the WASM module
let store = Store::new(&engine);
let module = Module::from_file(&store, &wasm_file)?;
module.serialize_to_file(&dylib_file)?;
assert!(dylib_file.exists());
println!("cargo:warning=Circuit dylib is in {}", dylib_file.display());

Ok(())
}

fn main() -> Result<()> {
for depth in semaphore_depth_config::get_supported_depths() {
build_circuit(*depth)?;
#[cfg(feature = "dylib")]
build_dylib(*depth)?;
}
Ok(())
}
Binary file added graphs/16/graph.bin
Binary file not shown.
Binary file added graphs/20/graph.bin
Binary file not shown.
Binary file added graphs/30/graph.bin
Binary file not shown.
69 changes: 5 additions & 64 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,89 +5,30 @@ use ark_relations::r1cs::ConstraintMatrices;
use core::include_bytes;
use once_cell::sync::{Lazy, OnceCell};

Check warning on line 6 in src/circuit.rs

View workflow job for this annotation

GitHub Actions / Test

unused import: `OnceCell`
use std::{io::Cursor, sync::Mutex};

Check warning on line 7 in src/circuit.rs

View workflow job for this annotation

GitHub Actions / Test

unused import: `sync::Mutex`
use wasmer::{Module, Store};

use semaphore_depth_config::{get_depth_index, get_supported_depth_count};
use semaphore_depth_macros::array_for_depths;
#[cfg(feature = "dylib")]
use std::{env, path::Path};
#[cfg(feature = "dylib")]
use wasmer::Dylib;

const ZKEY_BYTES: [&[u8]; get_supported_depth_count()] =
array_for_depths!(|depth| include_bytes!(env!(concat!("BUILD_RS_ZKEY_FILE_", depth))));

#[cfg(not(feature = "dylib"))]
const WASM: [&[u8]; get_supported_depth_count()] =
array_for_depths!(|depth| include_bytes!(env!(concat!("BUILD_RS_WASM_FILE_", depth))));
const GRAPH_BYTES: [&[u8]; get_supported_depth_count()] =
array_for_depths!(|depth| include_bytes!(env!(concat!("BUILD_RS_GRAPH_FILE_", depth))));

static ZKEY: [Lazy<(ProvingKey<Bn254>, ConstraintMatrices<Fr>)>; get_supported_depth_count()] =
array_for_depths!(|depth| Lazy::new(|| {
let mut reader = Cursor::new(ZKEY_BYTES[get_depth_index(depth).unwrap()]);
read_zkey(&mut reader).expect("zkey should be valid")
}));

static WITNESS_CALCULATOR: [OnceCell<Mutex<WitnessCalculator>>; get_supported_depth_count()] =
array_for_depths!(|_depth| OnceCell::new());

/// Initialize the library.
#[cfg(feature = "dylib")]
pub fn initialize(dylib_path: &Path, depth: usize) {
let index =
get_depth_index(depth).unwrap_or_else(|| panic!("depth {} is not supported", depth));
WITNESS_CALCULATOR[index]
.set(from_dylib(dylib_path))
.expect("Failed to initialize witness calculator");

// Force init of ZKEY
Lazy::force(&ZKEY[index]);
}

#[cfg(feature = "dylib")]
fn from_dylib(path: &Path) -> Mutex<WitnessCalculator> {
let store = Store::new(&Dylib::headless().engine());
// The module must be exported using [`Module::serialize`].
let module = unsafe {
Module::deserialize_from_file(&store, path).expect("Failed to load wasm dylib module")
};
let result =
WitnessCalculator::from_module(module).expect("Failed to create witness calculator");
Mutex::new(result)
}

#[must_use]
pub fn zkey(depth: usize) -> &'static (ProvingKey<Bn254>, ConstraintMatrices<Fr>) {
let index = get_depth_index(depth).unwrap_or_else(|| panic!("depth {depth} is not supported"));
&ZKEY[index]
}

#[cfg(feature = "dylib")]
#[must_use]
pub fn witness_calculator(depth: usize) -> &'static Mutex<WitnessCalculator> {
pub fn graph(depth: usize) -> &'static [u8] {
let index = get_depth_index(depth).unwrap_or_else(|| panic!("depth {depth} is not supported"));
let var_name = format!("CIRCUIT_WASM_DYLIB_{}", depth);
WITNESS_CALCULATOR[index].get_or_init(|| {
let path = env::var(&var_name).unwrap_or_else(|_| {
panic!(
"Semaphore-rs is not initialized. The library needs to be initialized before use \
when build with the `dylib` feature. You can initialize by calling `initialize` \
or setting the `{}` environment variable.",
var_name
)
});
from_dylib(Path::new(&path))
})
}

#[cfg(not(feature = "dylib"))]
#[must_use]
pub fn witness_calculator(depth: usize) -> &'static Mutex<WitnessCalculator> {
let index = get_depth_index(depth).unwrap_or_else(|| panic!("depth {depth} is not supported"));
WITNESS_CALCULATOR[index].get_or_init(|| {
let store = Store::default();
let module = Module::from_binary(&store, WASM[index]).expect("wasm should be valid");
let result =
WitnessCalculator::from_module(module).expect("Failed to create witness calculator");
Mutex::new(result)
})
}
&GRAPH_BYTES[index]
}
36 changes: 14 additions & 22 deletions src/protocol/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::{
circuit::{witness_calculator, zkey},
circuit::{zkey, graph},
identity::Identity,
merkle_tree::{self, Branch},
poseidon,
poseidon_tree::PoseidonHash,
Field,
};
use ark_bn254::{Bn254, Parameters};
use ark_bn254::{Parameters, Fr};
use ark_circom::CircomReduction;
use ark_ec::bn::Bn;
use ark_groth16::{
Expand All @@ -18,8 +18,9 @@ use color_eyre::Result;
use ethers_core::types::U256;
use rand::{thread_rng, Rng};
use serde::{Deserialize, Serialize};
use std::time::Instant;
use std::{time::Instant, collections::HashMap};
use thiserror::Error;
use ark_ff::PrimeField;

pub mod authentication;

Expand Down Expand Up @@ -144,28 +145,19 @@ fn generate_proof_rs(
s: ark_bn254::Fr,
) -> Result<Proof, ProofError> {
let depth = merkle_proof.0.len();
let inputs = [
("identityNullifier", vec![identity.nullifier]),
("identityTrapdoor", vec![identity.trapdoor]),
("treePathIndices", merkle_proof.path_index()),
("treeSiblings", merkle_proof_to_vec(merkle_proof)),
("externalNullifier", vec![external_nullifier_hash]),
("signalHash", vec![signal_hash]),
];
let inputs = inputs.into_iter().map(|(name, values)| {
(
name.to_string(),
values.iter().map(Into::into).collect::<Vec<_>>(),
)
});
let inputs = HashMap::from([
("identityNullifier".to_owned(), vec![identity.nullifier]),
("identityTrapdoor".to_owned(), vec![identity.trapdoor]),
("treePathIndices".to_owned(), merkle_proof.path_index()),
("treeSiblings".to_owned(), merkle_proof_to_vec(merkle_proof)),
("externalNullifier".to_owned(), vec![external_nullifier_hash]),
("signalHash".to_owned(), vec![signal_hash]),
]);

let now = Instant::now();

let full_assignment = witness_calculator(depth)
.lock()
.expect("witness_calculator mutex should not get poisoned")
.calculate_witness_element::<Bn254, _>(inputs, false)
.map_err(ProofError::WitnessError)?;
let witness = witness::calculate_witness(inputs, graph(depth)).unwrap();
let full_assignment = witness.into_iter().map(|x| Fr::from_repr(x.into()).unwrap()).collect::<Vec<_>>();

println!("witness generation took: {:.2?}", now.elapsed());

Expand Down

0 comments on commit 95cf9a2

Please sign in to comment.