#![doc = include_str!("../README.md")]
mod circuit;
mod field;
pub mod hash;
pub mod identity;
pub mod packed_proof;
pub mod poseidon_tree;
pub mod protocol;
pub use semaphore_rs_depth_config::get_supported_depths;
pub use crate::field::{hash_to_field, Field, MODULUS};
#[allow(dead_code)]
#[cfg(test)]
mod test {
use std::thread::spawn;
use semaphore_rs_depth_macros::test_all_depths;
use crate::identity::Identity;
use crate::poseidon_tree::LazyPoseidonTree;
use crate::protocol::{generate_nullifier_hash, generate_proof, verify_proof};
use crate::{hash_to_field, protocol, Field};
#[test]
fn test_field_serde() {
let value = Field::from(0x1234_5678);
let serialized = serde_json::to_value(value).unwrap();
let deserialized = serde_json::from_value(serialized).unwrap();
assert_eq!(value, deserialized);
}
fn test_end_to_end(
identity: &mut [u8],
external_nullifier: &[u8],
signal: &[u8],
depth: usize,
) {
let leaf = Field::from(0);
let id = Identity::from_secret(identity, None);
let mut tree = LazyPoseidonTree::new(depth, leaf).derived();
tree = tree.update(0, &id.commitment());
let merkle_proof = tree.proof(0);
let root = tree.root();
let signal_hash = hash_to_field(signal);
let external_nullifier_hash = hash_to_field(external_nullifier);
let nullifier_hash = generate_nullifier_hash(&id, external_nullifier_hash);
let proof =
generate_proof(&id, &merkle_proof, external_nullifier_hash, signal_hash).unwrap();
for _ in 0..5 {
let success = verify_proof(
root,
nullifier_hash,
signal_hash,
external_nullifier_hash,
&proof,
depth,
)
.unwrap();
assert!(success);
}
}
#[test_all_depths]
fn test_auth_flow(depth: usize) {
let mut secret = *b"oh so secret";
let id = Identity::from_secret(&mut secret[..], None);
let signal_hash = hash_to_field(b"signal");
let external_nullifier_hash = hash_to_field(b"appId");
let nullifier_hash = generate_nullifier_hash(&id, external_nullifier_hash);
let id_commitment = id.commitment();
let proof = protocol::authentication::generate_proof(
depth,
&id,
external_nullifier_hash,
signal_hash,
)
.unwrap();
let success = protocol::authentication::verify_proof(
depth,
id_commitment,
nullifier_hash,
signal_hash,
external_nullifier_hash,
&proof,
)
.unwrap();
assert!(success);
}
#[test_all_depths]
fn test_single(depth: usize) {
let mut hello = *b"hello";
test_end_to_end(&mut hello, b"appId", b"xxx", depth);
}
#[test_all_depths]
fn test_parallel(depth: usize) {
let mut a_id = *b"hello";
let mut b_id = *b"secret";
let a = spawn(move || test_end_to_end(&mut a_id, b"appId", b"xxx", depth));
let b = spawn(move || test_end_to_end(&mut b_id, b"test", b"signal", depth));
a.join().unwrap();
b.join().unwrap();
}
}