semaphore/
utils.rs

1use ark_ed_on_bn254::Fq;
2use ark_ff::{BigInteger, PrimeField};
3use ethers_core::utils::keccak256;
4use num_bigint::BigUint;
5use reqwest::blocking::Client;
6use std::error::Error;
7use std::fs::File;
8use std::io::copy;
9
10use crate::group::{EMPTY_ELEMENT, Element};
11
12pub fn string_to_biguint(num_str: &str) -> BigUint {
13    num_str
14        .parse()
15        .expect("Failed to parse the string into BigUint")
16}
17
18pub fn hash(message: BigUint) -> String {
19    let mut h = BigUint::from_bytes_be(&keccak256(message.to_bytes_be()));
20    h >>= 8;
21    h.to_string()
22}
23
24/// Converts a decimal string to BigUint and zero-pads it to 32 bytes (big-endian).
25pub fn to_big_uint(str: &String) -> BigUint {
26    let bytes = str.as_bytes();
27    assert!(bytes.len() <= 32, "BigUint too large: exceeds 32 bytes");
28    let mut fixed_bytes = [0u8; 32];
29    fixed_bytes[0..bytes.len()].copy_from_slice(bytes);
30    BigUint::from_bytes_be(&fixed_bytes)
31}
32
33/// Converts Fq to Element in little-endian order
34pub fn to_element(value: Fq) -> Element {
35    let mut element = EMPTY_ELEMENT;
36    let bytes = value.into_bigint().to_bytes_le();
37    element[..bytes.len()].copy_from_slice(&bytes);
38    element
39}
40
41/// Download zkey from artifacts: https://snark-artifacts.pse.dev/
42pub fn download_zkey(depth: u16) -> Result<String, Box<dyn Error>> {
43    let version = "4.13.0";
44    let base_url = format!("https://snark-artifacts.pse.dev/semaphore/{version}/");
45    let filename = format!("semaphore-{depth}.zkey");
46    let dest_filename = format!("semaphore-{version}-{depth}.zkey");
47    let out_dir = std::env::temp_dir();
48    let dest_path = out_dir.join(dest_filename.clone());
49    if !dest_path.exists() {
50        let url = format!("{base_url}{filename}");
51        let client = Client::new();
52        let mut resp = client.get(&url).send()?.error_for_status()?;
53        let mut out = File::create(&dest_path)?;
54        copy(&mut resp, &mut out)?;
55    }
56    Ok(dest_path.to_string_lossy().into_owned())
57}