mirror of
https://github.com/vacp2p/semaphore-rs.git
synced 2025-02-24 01:28:28 +00:00
snark file config and ffi lib
This commit is contained in:
parent
cc09d79f51
commit
0737ac5976
50
Cargo.lock
generated
50
Cargo.lock
generated
@ -2155,31 +2155,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsemaphore-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ark-bn254",
|
||||
"ark-circom",
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-groth16",
|
||||
"ark-relations",
|
||||
"ark-std",
|
||||
"color-eyre",
|
||||
"ethers",
|
||||
"ff_ce",
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"num-bigint 0.4.3",
|
||||
"once_cell",
|
||||
"poseidon-rs",
|
||||
"proptest",
|
||||
"rayon",
|
||||
"serde",
|
||||
"sha2 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.6"
|
||||
@ -3340,6 +3315,31 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semaphore"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ark-bn254",
|
||||
"ark-circom",
|
||||
"ark-ec",
|
||||
"ark-ff",
|
||||
"ark-groth16",
|
||||
"ark-relations",
|
||||
"ark-std",
|
||||
"color-eyre",
|
||||
"ethers",
|
||||
"ff_ce",
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"num-bigint 0.4.3",
|
||||
"once_cell",
|
||||
"poseidon-rs",
|
||||
"proptest",
|
||||
"rayon",
|
||||
"serde",
|
||||
"sha2 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.11.0"
|
||||
|
@ -5,8 +5,6 @@ edition = "2021"
|
||||
authors = [
|
||||
"Remco Bloemen <remco@worldcoin.org>",
|
||||
"Philipp Sippl <philipp@worldcoin.org>"]
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
homepage = "https://github.com/worldcoin/semaphore-rs"
|
||||
repository = "https://github.com/worldcoin/semaphore-rs"
|
||||
description = "Rust support library for Semaphore"
|
||||
|
8
cbindgen.toml
Normal file
8
cbindgen.toml
Normal file
@ -0,0 +1,8 @@
|
||||
language = "C"
|
||||
autogen_warning = "// NOTE: Append the lines below to ios/Classes/GreeterPlugin.h"
|
||||
#namespace = "ffi"
|
||||
#include_guard = "CBINDGEN_BINDINGS_H"
|
||||
|
||||
[defines]
|
||||
"target_os = ios" = "TARGET_OS_IOS"
|
||||
"target_os = macos" = "TARGET_OS_MACOS"
|
73
libsemaphore.h
Normal file
73
libsemaphore.h
Normal file
@ -0,0 +1,73 @@
|
||||
// NOTE: Append the lines below to ios/Classes/GreeterPlugin.h
|
||||
|
||||
typedef struct Identity Identity;
|
||||
|
||||
/**
|
||||
* Merkle tree with all leaf and intermediate hashes stored
|
||||
*/
|
||||
typedef struct MerkleTree_PoseidonHash MerkleTree_PoseidonHash;
|
||||
|
||||
/**
|
||||
* Merkle proof path, bottom to top.
|
||||
*/
|
||||
typedef struct Proof_Bn_Parameters Proof_Bn_Parameters;
|
||||
|
||||
/**
|
||||
* Merkle proof path, bottom to top.
|
||||
*/
|
||||
typedef struct Proof_PoseidonHash Proof_PoseidonHash;
|
||||
|
||||
typedef struct MerkleTree_PoseidonHash PoseidonTree;
|
||||
|
||||
/**
|
||||
* Creates a new idenity and returns the object
|
||||
*/
|
||||
struct Identity *new_identity(const char *seed);
|
||||
|
||||
/**
|
||||
* Generates the identity commitment based on seed for identity
|
||||
*/
|
||||
char *generate_identity_commitment(struct Identity *identity);
|
||||
|
||||
/**
|
||||
* Generates nullifier hash based on identity and external nullifier
|
||||
*/
|
||||
char *generate_nullifier_hash(struct Identity *identity, const char *external_nullifier);
|
||||
|
||||
/**
|
||||
* Generates nullifier hash based on identity and external nullifier
|
||||
*/
|
||||
PoseidonTree *create_poseidon_tree(int depth);
|
||||
|
||||
/**
|
||||
* Generates nullifier hash based on identity and external nullifier
|
||||
*/
|
||||
void insert_leaf(PoseidonTree *tree, struct Identity *identity);
|
||||
|
||||
/**
|
||||
* Generates nullifier hash based on identity and external nullifier
|
||||
*/
|
||||
char *get_root(PoseidonTree *tree);
|
||||
|
||||
/**
|
||||
* Generates nullifier hash based on identity and external nullifier
|
||||
*/
|
||||
struct Proof_PoseidonHash *get_merkle_proof(PoseidonTree *tree, int leaf_idx);
|
||||
|
||||
/**
|
||||
* Generates nullifier hash based on identity and external nullifier
|
||||
*/
|
||||
struct Proof_Bn_Parameters *generate_proof(struct Identity *identity,
|
||||
const char *external_nullifier,
|
||||
const char *signal,
|
||||
struct Proof_PoseidonHash *merkle_proof,
|
||||
const char *zkey_path,
|
||||
const char *wasm_path);
|
||||
|
||||
int verify_proof(const char *root,
|
||||
const char *external_nullifier,
|
||||
const char *signal,
|
||||
const char *nullifier,
|
||||
struct Proof_Bn_Parameters *proof,
|
||||
const char *zkey_path,
|
||||
const char *wasm_path);
|
232
src/lib.rs
232
src/lib.rs
@ -5,13 +5,24 @@ mod poseidon_tree;
|
||||
mod protocol;
|
||||
mod util;
|
||||
|
||||
use ark_bn254::Parameters;
|
||||
use ark_ec::bn::Bn;
|
||||
use ark_groth16::Proof;
|
||||
use hex_literal::hex;
|
||||
use num_bigint::{BigInt};
|
||||
use poseidon_tree::PoseidonHash;
|
||||
use protocol::SnarkFileConfig;
|
||||
use std::{
|
||||
ffi::{CStr, CString},
|
||||
os::raw::c_char,
|
||||
os::raw::{c_char, c_int},
|
||||
};
|
||||
|
||||
use crate::{hash::Hash, poseidon_tree::PoseidonTree};
|
||||
|
||||
/// Creates a new idenity and returns the object
|
||||
#[no_mangle]
|
||||
pub extern "C" fn generate_identity_commitment(seed: *const c_char) -> *mut c_char {
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn new_identity(seed: *const c_char) -> *mut identity::Identity {
|
||||
let c_str = unsafe { CStr::from_ptr(seed) };
|
||||
let seed = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
@ -19,7 +30,222 @@ pub extern "C" fn generate_identity_commitment(seed: *const c_char) -> *mut c_ch
|
||||
};
|
||||
let id = identity::Identity::new(seed.as_bytes());
|
||||
|
||||
CString::new(id.commitment().to_str_radix(10))
|
||||
let boxed: Box<identity::Identity> = Box::new(id);
|
||||
Box::into_raw(boxed)
|
||||
}
|
||||
|
||||
/// Generates the identity commitment based on seed for identity
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn generate_identity_commitment(
|
||||
identity: *mut identity::Identity,
|
||||
) -> *mut c_char {
|
||||
let identity = &*identity;
|
||||
CString::new(identity.commitment().to_str_radix(10))
|
||||
.unwrap()
|
||||
.into_raw()
|
||||
}
|
||||
|
||||
/// Generates nullifier hash based on identity and external nullifier
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn generate_nullifier_hash(
|
||||
identity: *mut identity::Identity,
|
||||
external_nullifier: *const c_char,
|
||||
) -> *mut c_char {
|
||||
let identity = &*identity;
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(external_nullifier) };
|
||||
let external_nullifier = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
CString::new(
|
||||
protocol::generate_nullifier_hash(identity, external_nullifier.as_bytes()).to_str_radix(10),
|
||||
)
|
||||
.unwrap()
|
||||
.into_raw()
|
||||
}
|
||||
|
||||
/// Generates nullifier hash based on identity and external nullifier
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn create_poseidon_tree(depth: c_int) -> *mut PoseidonTree {
|
||||
const LEAF: Hash = Hash::from_bytes_be(hex!(
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
));
|
||||
|
||||
let tree = PoseidonTree::new(depth as usize, LEAF);
|
||||
|
||||
let boxed: Box<PoseidonTree> = Box::new(tree);
|
||||
Box::into_raw(boxed)
|
||||
}
|
||||
|
||||
/// Generates nullifier hash based on identity and external nullifier
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn insert_leaf(tree: *mut PoseidonTree, identity: *mut identity::Identity) {
|
||||
let identity = &*identity;
|
||||
let tree = unsafe {
|
||||
assert!(!tree.is_null());
|
||||
&mut *tree
|
||||
};
|
||||
|
||||
let (_, leaf) = identity.commitment().to_bytes_be();
|
||||
tree.set(0, leaf.into());
|
||||
}
|
||||
|
||||
/// Generates nullifier hash based on identity and external nullifier
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn get_root(tree: *mut PoseidonTree) -> *mut c_char {
|
||||
let tree = unsafe {
|
||||
assert!(!tree.is_null());
|
||||
&mut *tree
|
||||
};
|
||||
|
||||
let root: BigInt = tree.root().into();
|
||||
CString::new(root.to_str_radix(10)).unwrap().into_raw()
|
||||
}
|
||||
|
||||
/// Generates nullifier hash based on identity and external nullifier
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn get_merkle_proof(
|
||||
tree: *mut PoseidonTree,
|
||||
leaf_idx: c_int,
|
||||
) -> *mut merkle_tree::Proof<PoseidonHash> {
|
||||
let tree = unsafe {
|
||||
assert!(!tree.is_null());
|
||||
&mut *tree
|
||||
};
|
||||
|
||||
let proof = tree.proof(leaf_idx as usize).expect("proof should exist");
|
||||
|
||||
let boxed: Box<merkle_tree::Proof<PoseidonHash>> = Box::new(proof);
|
||||
Box::into_raw(boxed)
|
||||
}
|
||||
|
||||
/// Generates nullifier hash based on identity and external nullifier
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn generate_proof(
|
||||
identity: *mut identity::Identity,
|
||||
external_nullifier: *const c_char,
|
||||
signal: *const c_char,
|
||||
merkle_proof: *mut merkle_tree::Proof<PoseidonHash>,
|
||||
zkey_path: *const c_char,
|
||||
wasm_path: *const c_char,
|
||||
) -> *mut Proof<Bn<Parameters>> {
|
||||
let c_str = unsafe { CStr::from_ptr(external_nullifier) };
|
||||
let external_nullifier = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(signal) };
|
||||
let signal = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(zkey_path) };
|
||||
let zkey_path = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(wasm_path) };
|
||||
let wasm_path = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let config = SnarkFileConfig {
|
||||
zkey: zkey_path.to_string(),
|
||||
wasm: wasm_path.to_string(),
|
||||
};
|
||||
|
||||
let identity = &*identity;
|
||||
let merkle_proof = &*merkle_proof;
|
||||
|
||||
let res = protocol::generate_proof(
|
||||
&config,
|
||||
identity,
|
||||
merkle_proof,
|
||||
external_nullifier.as_bytes(),
|
||||
signal.as_bytes(),
|
||||
);
|
||||
|
||||
let boxed: Box<Proof<Bn<Parameters>>> = Box::new(res.unwrap());
|
||||
Box::into_raw(boxed)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn verify_proof(
|
||||
root: *const c_char,
|
||||
external_nullifier: *const c_char,
|
||||
signal: *const c_char,
|
||||
nullifier: *const c_char,
|
||||
proof: *mut Proof<Bn<Parameters>>,
|
||||
zkey_path: *const c_char,
|
||||
wasm_path: *const c_char,
|
||||
) -> c_int {
|
||||
let c_str = unsafe { CStr::from_ptr(root) };
|
||||
let root = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(external_nullifier) };
|
||||
let external_nullifier = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(signal) };
|
||||
let signal = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(nullifier) };
|
||||
let nullifier = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(zkey_path) };
|
||||
let zkey_path = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let c_str = unsafe { CStr::from_ptr(wasm_path) };
|
||||
let wasm_path = match c_str.to_str() {
|
||||
Err(_) => "there",
|
||||
Ok(string) => string,
|
||||
};
|
||||
|
||||
let config = SnarkFileConfig {
|
||||
zkey: zkey_path.to_string(),
|
||||
wasm: wasm_path.to_string(),
|
||||
};
|
||||
|
||||
let proof = &*proof;
|
||||
|
||||
let root = BigInt::parse_bytes(root.as_bytes(), 10).unwrap();
|
||||
let nullifier = BigInt::parse_bytes(nullifier.as_bytes(), 10).unwrap();
|
||||
|
||||
protocol::verify_proof(
|
||||
&config,
|
||||
&root,
|
||||
&nullifier,
|
||||
signal.as_bytes(),
|
||||
external_nullifier.as_bytes(),
|
||||
proof,
|
||||
)
|
||||
.unwrap() as i32
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
const char* generate_identity_commitment(const char* to);
|
13
src/main.rs
13
src/main.rs
@ -8,7 +8,7 @@ mod util;
|
||||
use hash::*;
|
||||
use hex_literal::hex;
|
||||
use identity::*;
|
||||
use num_bigint::BigInt;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use poseidon_rs::Poseidon;
|
||||
use poseidon_tree::*;
|
||||
use protocol::*;
|
||||
@ -38,12 +38,17 @@ fn main() {
|
||||
let signal = "xxx".as_bytes();
|
||||
let external_nullifier = "appId".as_bytes();
|
||||
|
||||
let nullifier_hash = generate_nullifier_hash(&external_nullifier, &id.nullifier);
|
||||
let nullifier_hash = generate_nullifier_hash(&id, external_nullifier);
|
||||
dbg!(&nullifier_hash);
|
||||
|
||||
let proof = generate_proof(&id, &merkle_proof, &external_nullifier, &signal).unwrap();
|
||||
let config = SnarkFileConfig {
|
||||
zkey: "./snarkfiles/semaphore.zkey".to_string(),
|
||||
wasm: "./snarkfiles/semaphore.wasm".to_string(),
|
||||
};
|
||||
|
||||
let proof = generate_proof(&config, &id, &merkle_proof, external_nullifier, signal).unwrap();
|
||||
let success =
|
||||
verify_proof(&root, &nullifier_hash, &signal, &external_nullifier, &proof).unwrap();
|
||||
verify_proof(&config, &root, &nullifier_hash, signal, external_nullifier, &proof).unwrap();
|
||||
|
||||
dbg!(success);
|
||||
}
|
||||
|
@ -19,11 +19,13 @@ use crate::{
|
||||
util::{bigint_to_fr, fr_to_bigint},
|
||||
};
|
||||
|
||||
static SNARK_FILES: &str = "./snarkfiles/";
|
||||
static ZKEY_FILE: &str = "semaphore.zkey";
|
||||
static WASM_FILE: &str = "semaphore.wasm";
|
||||
static POSEIDON: Lazy<Poseidon> = Lazy::new(Poseidon::new);
|
||||
|
||||
pub struct SnarkFileConfig {
|
||||
pub zkey: String,
|
||||
pub wasm: String,
|
||||
}
|
||||
|
||||
/// Helper to merkle proof into a bigint vector
|
||||
/// TODO: we should create a From trait for this
|
||||
fn merkle_proof_to_vec(proof: &merkle_tree::Proof<PoseidonHash>) -> Vec<BigInt> {
|
||||
@ -50,11 +52,11 @@ pub fn hash_external_nullifier(nullifier: &[u8]) -> BigInt {
|
||||
}
|
||||
|
||||
/// Generates the nullifier hash
|
||||
pub fn generate_nullifier_hash(external_nullifier: &[u8], identity_nullifier: &BigInt) -> BigInt {
|
||||
pub fn generate_nullifier_hash(identity: &Identity, external_nullifier: &[u8]) -> BigInt {
|
||||
let res = POSEIDON
|
||||
.hash(vec![
|
||||
bigint_to_fr(&hash_external_nullifier(external_nullifier)),
|
||||
bigint_to_fr(identity_nullifier),
|
||||
bigint_to_fr(&identity.nullifier),
|
||||
])
|
||||
.unwrap();
|
||||
fr_to_bigint(res)
|
||||
@ -62,12 +64,13 @@ pub fn generate_nullifier_hash(external_nullifier: &[u8], identity_nullifier: &B
|
||||
|
||||
/// Generates a semaphore proof
|
||||
pub fn generate_proof(
|
||||
config: &SnarkFileConfig,
|
||||
identity: &Identity,
|
||||
merkle_proof: &merkle_tree::Proof<PoseidonHash>,
|
||||
external_nullifier: &[u8],
|
||||
signal: &[u8],
|
||||
) -> Result<Proof<Bn<Parameters>>, SynthesisError> {
|
||||
let mut file = File::open(format!("{}{}", SNARK_FILES, ZKEY_FILE)).unwrap();
|
||||
let mut file = File::open(&config.zkey).unwrap();
|
||||
let (params, matrices) = read_zkey(&mut file).unwrap();
|
||||
let num_inputs = matrices.num_instance_variables;
|
||||
let num_constraints = matrices.num_constraints;
|
||||
@ -97,7 +100,7 @@ pub fn generate_proof(
|
||||
use std::time::Instant;
|
||||
let now = Instant::now();
|
||||
|
||||
let mut wtns = WitnessCalculator::new(format!("{}{}", SNARK_FILES, WASM_FILE)).unwrap();
|
||||
let mut wtns = WitnessCalculator::new(&config.wasm).unwrap();
|
||||
|
||||
let full_assignment = wtns
|
||||
.calculate_witness_element::<Bn254, _>(inputs, false)
|
||||
@ -131,13 +134,14 @@ pub fn generate_proof(
|
||||
|
||||
/// Verifies a given semaphore proof
|
||||
pub fn verify_proof(
|
||||
config: &SnarkFileConfig,
|
||||
root: &BigInt,
|
||||
nullifier_hash: &BigInt,
|
||||
signal: &[u8],
|
||||
external_nullifier: &[u8],
|
||||
proof: &Proof<Bn<Parameters>>,
|
||||
) -> Result<bool, SynthesisError> {
|
||||
let mut file = File::open(format!("{}{}", SNARK_FILES, ZKEY_FILE)).unwrap();
|
||||
let mut file = File::open(&config.zkey).unwrap();
|
||||
let (params, _) = read_zkey(&mut file).unwrap();
|
||||
|
||||
let pvk = prepare_verifying_key(¶ms.vk);
|
||||
|
Loading…
x
Reference in New Issue
Block a user