1#![doc = include_str!("../README.md")]
2
3mod circuit;
4mod field;
5pub mod hash;
6pub mod identity;
7pub mod packed_proof;
8pub mod poseidon_tree;
9pub mod protocol;
10
11pub use semaphore_rs_depth_config::get_supported_depths;
12
13pub use crate::field::{hash_to_field, Field, MODULUS};
15
16#[allow(dead_code)]
17#[cfg(test)]
18mod test {
19 use std::thread::spawn;
20
21 use semaphore_rs_depth_macros::test_all_depths;
22
23 use crate::identity::Identity;
24 use crate::poseidon_tree::LazyPoseidonTree;
25 use crate::protocol::{generate_nullifier_hash, generate_proof, verify_proof};
26 use crate::{hash_to_field, protocol, Field};
27
28 #[test]
29 fn test_field_serde() {
30 let value = Field::from(0x1234_5678);
31 let serialized = serde_json::to_value(value).unwrap();
32 let deserialized = serde_json::from_value(serialized).unwrap();
33 assert_eq!(value, deserialized);
34 }
35
36 fn test_end_to_end(
37 identity: &mut [u8],
38 external_nullifier: &[u8],
39 signal: &[u8],
40 depth: usize,
41 ) {
42 let leaf = Field::from(0);
43
44 let id = Identity::from_secret(identity, None);
46
47 let mut tree = LazyPoseidonTree::new(depth, leaf).derived();
49 tree = tree.update(0, &id.commitment());
50
51 let merkle_proof = tree.proof(0);
52 let root = tree.root();
53
54 let signal_hash = hash_to_field(signal);
55 let external_nullifier_hash = hash_to_field(external_nullifier);
56 let nullifier_hash = generate_nullifier_hash(&id, external_nullifier_hash);
57
58 let proof =
59 generate_proof(&id, &merkle_proof, external_nullifier_hash, signal_hash).unwrap();
60
61 for _ in 0..5 {
62 let success = verify_proof(
63 root,
64 nullifier_hash,
65 signal_hash,
66 external_nullifier_hash,
67 &proof,
68 depth,
69 )
70 .unwrap();
71 assert!(success);
72 }
73 }
74
75 #[test_all_depths]
76 fn test_auth_flow(depth: usize) {
77 let mut secret = *b"oh so secret";
78 let id = Identity::from_secret(&mut secret[..], None);
79 let signal_hash = hash_to_field(b"signal");
80 let external_nullifier_hash = hash_to_field(b"appId");
81 let nullifier_hash = generate_nullifier_hash(&id, external_nullifier_hash);
82 let id_commitment = id.commitment();
83
84 let proof = protocol::authentication::generate_proof(
85 depth,
86 &id,
87 external_nullifier_hash,
88 signal_hash,
89 )
90 .unwrap();
91
92 let success = protocol::authentication::verify_proof(
93 depth,
94 id_commitment,
95 nullifier_hash,
96 signal_hash,
97 external_nullifier_hash,
98 &proof,
99 )
100 .unwrap();
101 assert!(success);
102 }
103
104 #[test_all_depths]
105 fn test_single(depth: usize) {
106 let mut hello = *b"hello";
108 test_end_to_end(&mut hello, b"appId", b"xxx", depth);
109 }
110
111 #[test_all_depths]
112 fn test_parallel(depth: usize) {
113 let mut a_id = *b"hello";
117 let mut b_id = *b"secret";
118 let a = spawn(move || test_end_to_end(&mut a_id, b"appId", b"xxx", depth));
119 let b = spawn(move || test_end_to_end(&mut b_id, b"test", b"signal", depth));
120 a.join().unwrap();
121 b.join().unwrap();
122 }
123}