Skip to content

Commit 8f062c4

Browse files
authored
Merge pull request #7 from semaphore-protocol/feat/implement_proof_gen
Feat/implement proof gen
2 parents 6f00c4b + 2492bad commit 8f062c4

File tree

8 files changed

+3797
-275
lines changed

8 files changed

+3797
-275
lines changed

Cargo.lock

Lines changed: 3203 additions & 236 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ blake = "2.0.2"
88
light-poseidon = "0.3.0"
99
num-bigint = "0.4.6"
1010
thiserror = "2.0.12"
11+
ruint = "1.14.0"
12+
num-traits = "0.2.19"
13+
ethers-core = "2.0.14"
14+
anyhow = "1.0.97"
15+
reqwest = { version = "0.12.15", features = ["blocking", "json"] }
16+
tokio = { version = "1", features = ["full"] }
1117

1218
# arkworks
1319
ark-ec = { version = "=0.5.0", default-features = false }
@@ -21,10 +27,18 @@ zk-kit-lean-imt = { git = "https://github.com/brech1/zk-kit.rust", package = "zk
2127
serde = { version = "1", features = ["derive"], optional = true }
2228
serde_json = { version = "1", optional = true }
2329

30+
# circom-prover
31+
rust-witness = "0.1"
32+
circom-prover = "=0.1.1"
33+
2434
[features]
25-
default = []
35+
default = ["serde"]
2636
serde = [
2737
"dep:serde",
2838
"serde_json",
2939
"zk-kit-lean-imt/serde"
3040
]
41+
42+
[build-dependencies]
43+
rust-witness = "0.1"
44+
reqwest = { version = "0.12.15", features = ["blocking", "json"] }

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,19 @@
6767

6868
All tasks related to the Semaphore Rust implementation are public. You can track their progress, statuses, and additional details in the [Semaphore Rust view](https://github.com/orgs/semaphore-protocol/projects/10/views/29).
6969

70+
71+
72+
## 🛠 Install
73+
74+
Clone this repository:
75+
76+
```bash
77+
git clone git@github.com:semaphore-protocol/semaphore-rs.git
78+
```
79+
80+
Semaphore uses `Circom-Prover` to generate zero-knowledge proofs for `Circom` circuits. Since `Circom-Prover` generates the witness function at build time, developers must specify the Merkle tree depth during compilation. This can be done by setting the `SEMAPHORE_DEPTH` environment variable:
81+
82+
```bash
83+
cd semaphore-rs
84+
SEMAPHORE_DEPTH=<tree depth> cargo build
85+
```

build.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use reqwest::blocking::Client;
2+
use std::error::Error;
3+
use std::fs::{File, create_dir_all};
4+
use std::io::copy;
5+
use std::path::{Path, PathBuf};
6+
7+
/// download semaphore artifacts by required tree depth
8+
fn download_semaphore_artifacts(depth: usize) -> Result<(), Box<dyn Error>> {
9+
let base_url = "https://snark-artifacts.pse.dev/semaphore/latest/";
10+
let remote_filenames = [
11+
format!("semaphore-{}.wasm", depth),
12+
format!("semaphore-{}.zkey", depth),
13+
];
14+
let local_filenames = ["semaphore.wasm", "semaphore.zkey"];
15+
16+
let client = Client::new();
17+
let target_dir = Path::new("./zkey");
18+
19+
// Verify if those files have been downloaded or not. Skip downloading if yes.
20+
let version_path = target_dir.join("depth");
21+
if version_path.exists() {
22+
let current_version = std::fs::read_to_string(&version_path)?.trim().to_string();
23+
if current_version == depth.to_string() {
24+
println!(
25+
"Artifacts for depth {} already downloaded, skipping.",
26+
depth
27+
);
28+
return Ok(());
29+
}
30+
}
31+
// create ./zkey folder
32+
create_dir_all(target_dir)?;
33+
34+
// download artifacts
35+
for (remote, local) in remote_filenames.iter().zip(local_filenames.iter()) {
36+
let url = format!("{}{}", base_url, remote);
37+
let dest_path: PathBuf = target_dir.join(local);
38+
39+
eprintln!("Downloading {}...", url);
40+
let mut resp = client.get(&url).send()?.error_for_status()?;
41+
let mut out = File::create(&dest_path)?;
42+
copy(&mut resp, &mut out)?;
43+
eprintln!("Saved as {}", dest_path.display());
44+
}
45+
46+
// update depth info
47+
std::fs::write(&version_path, depth.to_string())?;
48+
49+
Ok(())
50+
}
51+
52+
fn main() {
53+
// Default depth is 10 for testing purposes; can be overridden via SEMAPHORE_DEPTH environment variable
54+
let depth: usize = std::env::var("SEMAPHORE_DEPTH")
55+
.unwrap_or_else(|_| "10".to_string())
56+
.parse()
57+
.expect("SEMAPHORE_DEPTH must be a valid usize");
58+
59+
if depth > 32 {
60+
panic!("The tree depth must be less than 32.");
61+
}
62+
63+
download_semaphore_artifacts(depth).expect("Failed to download artifacts");
64+
65+
rust_witness::transpile::transpile_wasm("./zkey".to_string());
66+
}

src/group.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use ark_ff::{BigInteger, PrimeField};
1010
use light_poseidon::{Poseidon, PoseidonHasher};
1111
use zk_kit_lean_imt::{
1212
hashed_tree::{HashedLeanIMT, LeanIMTHasher},
13-
lean_imt::MerkleProof,
13+
lean_imt,
1414
};
1515

1616
/// Size of nodes and leaves in bytes
@@ -21,6 +21,9 @@ pub const EMPTY_ELEMENT: Element = [0u8; ELEMENT_SIZE];
2121
/// Element type alias
2222
pub type Element = [u8; ELEMENT_SIZE];
2323

24+
/// Merkle proof alias
25+
pub type MerkleProof = lean_imt::MerkleProof<ELEMENT_SIZE>;
26+
2427
/// Poseidon LeanIMT hasher
2528
#[derive(Debug, Default, Clone, PartialEq, Eq)]
2629
pub struct PoseidonHash;
@@ -140,17 +143,14 @@ impl Group {
140143
}
141144

142145
/// Creates a proof of membership for a member
143-
pub fn generate_proof(
144-
&self,
145-
index: usize,
146-
) -> Result<MerkleProof<ELEMENT_SIZE>, SemaphoreError> {
146+
pub fn generate_proof(&self, index: usize) -> Result<MerkleProof, SemaphoreError> {
147147
self.tree
148148
.generate_proof(index)
149149
.map_err(SemaphoreError::LeanIMTError)
150150
}
151151

152152
/// Verifies a proof of membership for a member
153-
pub fn verify_proof(proof: &MerkleProof<ELEMENT_SIZE>) -> bool {
153+
pub fn verify_proof(proof: &MerkleProof) -> bool {
154154
HashedLeanIMT::<ELEMENT_SIZE, PoseidonHash>::verify_proof(proof)
155155
}
156156
}

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ pub mod group;
99
pub mod identity;
1010
pub mod proof;
1111
pub mod utils;
12+
13+
pub const MIN_TREE_DEPTH: u16 = 1;
14+
pub const MAX_TREE_DEPTH: u16 = 32;

0 commit comments

Comments
 (0)