refactor: use tests and crates folders

This commit is contained in:
Ya-wen, Jeng 2025-02-05 10:09:35 +08:00
parent 1d32c928c8
commit d4a4c65d2d
77 changed files with 341 additions and 241 deletions

View File

@ -1,2 +0,0 @@
[env]
RUST_RAPIDSNARK_LINK_TEST_WITNESS="1"

95
Cargo.lock generated
View File

@ -31,12 +31,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "jobserver"
version = "0.1.32"
@ -52,12 +46,6 @@ version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "num-bigint"
version = "0.4.6"
@ -92,24 +80,6 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "proc-macro2"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rust-rapidsnark"
version = "0.1.0"
@ -118,16 +88,13 @@ dependencies = [
"cc",
"num-bigint",
"num-traits",
"rust-witness",
"serde",
"serde_json",
]
[[package]]
name = "rust-witness"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a367cd88f01e03d529bcfcf0837169a53f8e14c5acf6948c4e556f27b78aef2"
checksum = "aedca7c326ffe9ebb93e282f28d00971139b01c555b9892f450f8b1b3bfbba50"
dependencies = [
"cc",
"fnv",
@ -137,12 +104,6 @@ dependencies = [
"walkdir",
]
[[package]]
name = "ryu"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "same-file"
version = "1.0.6"
@ -152,38 +113,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "serde"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
@ -191,22 +120,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
name = "tests"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
"anyhow",
"num-bigint",
"num-traits",
"rust-rapidsnark",
"rust-witness",
]
[[package]]
name = "unicode-ident"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
[[package]]
name = "walkdir"
version = "2.5.0"

View File

@ -1,18 +1,3 @@
[package]
name = "rust-rapidsnark"
version = "0.1.0"
edition = "2021"
[lib]
[dependencies]
anyhow = "1.0.95"
num-bigint = "0.4.6"
rust-witness = "0.1.2"
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0.135"
num-traits = "0.2.19"
[build-dependencies]
cc = "1.0"
rust-witness = "0.1.2"
[workspace]
members = ["crates", "tests"]
resolver = "2"

View File

@ -1,3 +1,88 @@
# rust-rapidsnark
# Rust Rapidsnark
Rust bindings for the [rapidsnark](https://github.com/iden3/rapidsnark/) prover.
<!-- [![Crates.io](https://img.shields.io/crates/v/witnesscalc-adapter?label=witnesscalc-adapter)](https://crates.io/crates/witnesscalc-adapter) -->
This project provides a Rust adapter for compiling and linking [Rapidsnark](https://github.com/iden3/rapidsnark) into a native library for target platforms (e.g., mobile devices). It includes macros and functions to facilitate the integration of proof generation into Rust codebases.
## Usage
Include the crate in your `Cargo.toml`:
```toml
[dependencies]
rust-rapidsnark = "0.1.0"
[build-dependencies]
rust-rapidsnark = "0.1.0"
```
It doesn't include the witness generation functions, you need to use one of the following crates to generate the witness:
- [rust-witness](https://github.com/chancehudson/rust-witness)
- [witnesscalc-adapter](https://github.com/zkmopro/witnesscalc_adapter)
- [circom-witnesscalc](https://github.com/iden3/circom-witnesscalc)
- [wasmer](https://github.com/wasmerio/wasmer)
For example, building witness with `witnesscalc-adapter`:
```rust
witnesscalc_adapter::witness!(multiplier2);
let json_input_string = "{\"a\": [\"2\"], \"b\": [\"3\"]}";;
let wtns_buffer = multiplier2_witness(json_input_string).unwrap();
```
### Calculate the proof
Calculate the proof by using the `groth16_prover_zkey_file_wrapper` function.
It will take a `wtns` bytes array like the output of [witnesscalc](https://github.com/0xPolygonID/witnesscalc) or [snarkjs](https://github.com/iden3/snarkjs).
```rust
let zkey_path = "./test-vectors/multiplier2_final.zkey".to_string();
let proof = rust_rapidsnark::groth16_prover_zkey_file_wrapper(&zkey_path, wtns_buffer).unwrap();
```
### Verify the proof
Verify the proof by using the `groth16_verifier_zkey_file_wrapper` function.
```rust
let vkey = std::fs::read_to_string("./test-vectors/keccak256_256_test.vkey.json")?;
let valid = rust_rapidsnark::groth16_verify_wrapper(
&proof.proof,
&proof.public_signals,
&vkey,
)?;
```
## Supported platforms
### Linux
- x86_64 linux
- arm64 linux
### MacOS
- aarch64-apple-darwin
- x86_64-apple-darwin
### iOS
- aarch64-apple-ios
- aarch64-apple-ios-sim
- x86_64-apple-ios
### Android
- aarch64-linux-android
- x86_64-linux-android
## Community
- Website: [zkmopro.com](https://zkmopro.com)
- X account: <a href="https://twitter.com/zkmopro"><img src="https://img.shields.io/twitter/follow/zkmopro?style=flat-square&logo=x&label=zkmopro"></a>
- Telegram group: <a href="https://t.me/zkmopro"><img src="https://img.shields.io/badge/telegram-@zkmopro-blue.svg?style=flat-square&logo=telegram"></a>
## Acknowledgements
- The project is sponsored by [PSE](https://pse.dev/).

18
crates/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "rust-rapidsnark"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/zkmopro/rust-rapidsnark"
documentation = "https://zkmopro.org/"
homepage = "https://zkmopro.org/"
[lib]
[dependencies]
anyhow = "1.0.95"
num-bigint = "0.4.6"
num-traits = "0.2.19"
[build-dependencies]
cc = "1.0"

88
crates/README.md Normal file
View File

@ -0,0 +1,88 @@
# Rust Rapidsnark
<!-- [![Crates.io](https://img.shields.io/crates/v/witnesscalc-adapter?label=witnesscalc-adapter)](https://crates.io/crates/witnesscalc-adapter) -->
This project provides a Rust adapter for compiling and linking [Rapidsnark](https://github.com/iden3/rapidsnark) into a native library for target platforms (e.g., mobile devices). It includes macros and functions to facilitate the integration of proof generation into Rust codebases.
## Usage
Include the crate in your `Cargo.toml`:
```toml
[dependencies]
rust-rapidsnark = "0.1.0"
[build-dependencies]
rust-rapidsnark = "0.1.0"
```
It doesn't include the witness generation functions, you need to use one of the following crates to generate the witness:
- [rust-witness](https://github.com/chancehudson/rust-witness)
- [witnesscalc-adapter](https://github.com/zkmopro/witnesscalc_adapter)
- [circom-witnesscalc](https://github.com/iden3/circom-witnesscalc)
- [wasmer](https://github.com/wasmerio/wasmer)
For example, building witness with `witnesscalc-adapter`:
```rust
witnesscalc_adapter::witness!(multiplier2);
let json_input_string = "{\"a\": [\"2\"], \"b\": [\"3\"]}";;
let wtns_buffer = multiplier2_witness(json_input_string).unwrap();
```
### Calculate the proof
Calculate the proof by using the `groth16_prover_zkey_file_wrapper` function.
It will take a `wtns` bytes array like the output of [witnesscalc](https://github.com/0xPolygonID/witnesscalc) or [snarkjs](https://github.com/iden3/snarkjs).
```rust
let zkey_path = "./test-vectors/multiplier2_final.zkey".to_string();
let proof = rust_rapidsnark::groth16_prover_zkey_file_wrapper(&zkey_path, wtns_buffer).unwrap();
```
### Verify the proof
Verify the proof by using the `groth16_verifier_zkey_file_wrapper` function.
```rust
let vkey = std::fs::read_to_string("./test-vectors/keccak256_256_test.vkey.json")?;
let valid = rust_rapidsnark::groth16_verify_wrapper(
&proof.proof,
&proof.public_signals,
&vkey,
)?;
```
## Supported platforms
### Linux
- x86_64 linux
- arm64 linux
### MacOS
- aarch64-apple-darwin
- x86_64-apple-darwin
### iOS
- aarch64-apple-ios
- aarch64-apple-ios-sim
- x86_64-apple-ios
### Android
- aarch64-linux-android
- x86_64-linux-android
## Community
- Website: [zkmopro.com](https://zkmopro.com)
- X account: <a href="https://twitter.com/zkmopro"><img src="https://img.shields.io/twitter/follow/zkmopro?style=flat-square&logo=x&label=zkmopro"></a>
- Telegram group: <a href="https://t.me/zkmopro"><img src="https://img.shields.io/badge/telegram-@zkmopro-blue.svg?style=flat-square&logo=telegram"></a>
## Acknowledgements
- The project is sponsored by [PSE](https://pse.dev/).

View File

@ -4,10 +4,6 @@ use std::path::Path;
use std::path::PathBuf;
fn main() {
if std::env::var("RUST_RAPIDSNARK_LINK_TEST_WITNESS").is_ok() {
rust_witness::transpile::transpile_wasm("./test-vectors".to_string());
}
let target = std::env::var("TARGET").unwrap();
let arch = target.split('-').next().unwrap();

View File

@ -30,6 +30,7 @@ pub struct ProofResult {
pub public_signals: String,
}
#[link(name = "rapidsnark", kind = "static")]
extern "C" {
pub fn groth16_prover_zkey_file(
zkey_file_path: *const std::os::raw::c_char,
@ -185,119 +186,3 @@ pub fn groth16_verify_wrapper(proof: &str, inputs: &str, verification_key: &str)
Ok(result == 0)
}
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use num_bigint::BigInt;
use std::{collections::HashMap, str::FromStr};
use crate::{parse_bigints_to_witness, WtnsFn};
rust_witness::witness!(multiplier2);
rust_witness::witness!(keccak256256test);
fn bytes_to_bits(bytes: &[u8]) -> Vec<bool> {
let mut bits = Vec::new();
for &byte in bytes {
for j in 0..8 {
let bit = (byte >> j) & 1;
bits.push(bit == 1);
}
}
bits
}
fn bytes_to_circuit_inputs(input_vec: &[u8]) -> HashMap<String, Vec<String>> {
let bits = bytes_to_bits(input_vec);
let converted_vec: Vec<String> = bits
.into_iter()
.map(|bit| (bit as i32).to_string())
.collect();
let mut inputs = HashMap::new();
inputs.insert("in".to_string(), converted_vec);
inputs
}
fn compute_witness(
inputs: HashMap<String, Vec<String>>,
witness_fn: WtnsFn,
) -> Result<Vec<u8>> {
// Form the inputs
let bigint_inputs = inputs
.into_iter()
.map(|(k, v)| {
(
k,
v.into_iter()
.map(|i| BigInt::from_str(&i).unwrap())
.collect(),
)
})
.collect();
let wtns: Vec<BigInt> = witness_fn(bigint_inputs);
let witnesscalc_wtns = parse_bigints_to_witness(wtns)?;
Ok(witnesscalc_wtns)
}
#[test]
fn test_prove_rapidsnark() -> Result<()> {
// Create a new MoproCircom instance
let zkey_path = "./test-vectors/multiplier2_final.zkey".to_string();
let mut inputs = HashMap::new();
let a = BigInt::from_str(
"21888242871839275222246405745257275088548364400416034343698204186575808495616",
)
.unwrap();
let b = BigInt::from(1u8);
inputs.insert("a".to_string(), vec![a.to_string()]);
inputs.insert("b".to_string(), vec![b.to_string()]);
// Generate Witness Buffer
let wtns_buffer = compute_witness(inputs, multiplier2_witness)?;
// Generate Proof
let proof_result = super::groth16_prover_zkey_file_wrapper(&zkey_path, wtns_buffer)?;
let vkey = std::fs::read_to_string("./test-vectors/multiplier2.vkey.json")?;
let valid = super::groth16_verify_wrapper(
&proof_result.proof,
&proof_result.public_signals,
&vkey,
)?;
assert!(valid);
Ok(())
}
#[test]
fn test_prove_rapidsnark_keccak() -> Result<()> {
// Create a new MoproCircom instance
let zkey_path = "./test-vectors/keccak256_256_test_final.zkey".to_string();
// Prepare inputs
let input_vec = vec![
116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
];
let inputs = bytes_to_circuit_inputs(&input_vec);
// Generate Witness Buffer
let wtns_buffer = compute_witness(inputs, keccak256256test_witness)?;
let wtns_data = std::fs::read("./test-vectors/keccak256_256_test.wtns")?;
assert_eq!(wtns_buffer, wtns_data);
// Generate Proof
let proof_result = super::groth16_prover_zkey_file_wrapper(&zkey_path, wtns_buffer)?;
let vkey = std::fs::read_to_string("./test-vectors/keccak256_256_test.vkey.json")?;
let valid = super::groth16_verify_wrapper(
&proof_result.proof,
&proof_result.public_signals,
&vkey,
)?;
assert!(valid);
Ok(())
}
}

View File

@ -1,13 +0,0 @@
#!/bin/sh
set -e
BUILD_DIR=$(mktemp -d)
git clone https://github.com/chancehudson/rapidsnark.git $BUILD_DIR
cd $BUILD_DIR
git submodule init
git submodule update
build_gmp.sh

15
tests/Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "tests"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.95"
num-bigint = "0.4.6"
num-traits = "0.2.19"
rust-rapidsnark = { path = "../crates" }
rust-witness = "0.1.3"
[build-dependencies]
rust-rapidsnark = { path = "../crates" }
rust-witness = "0.1.3"

3
tests/build.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
rust_witness::transpile::transpile_wasm("./test-vectors".to_string());
}

117
tests/src/lib.rs Normal file
View File

@ -0,0 +1,117 @@
#[cfg(test)]
mod tests {
use anyhow::Result;
use num_bigint::BigInt;
use std::{collections::HashMap, str::FromStr};
use rust_rapidsnark::{parse_bigints_to_witness, WtnsFn};
rust_witness::witness!(multiplier2);
rust_witness::witness!(keccak256256test);
fn bytes_to_bits(bytes: &[u8]) -> Vec<bool> {
let mut bits = Vec::new();
for &byte in bytes {
for j in 0..8 {
let bit = (byte >> j) & 1;
bits.push(bit == 1);
}
}
bits
}
fn bytes_to_circuit_inputs(input_vec: &[u8]) -> HashMap<String, Vec<String>> {
let bits = bytes_to_bits(input_vec);
let converted_vec: Vec<String> = bits
.into_iter()
.map(|bit| (bit as i32).to_string())
.collect();
let mut inputs = HashMap::new();
inputs.insert("in".to_string(), converted_vec);
inputs
}
fn compute_witness(
inputs: HashMap<String, Vec<String>>,
witness_fn: WtnsFn,
) -> Result<Vec<u8>> {
// Form the inputs
let bigint_inputs = inputs
.into_iter()
.map(|(k, v)| {
(
k,
v.into_iter()
.map(|i| BigInt::from_str(&i).unwrap())
.collect(),
)
})
.collect();
let wtns: Vec<BigInt> = witness_fn(bigint_inputs);
let witnesscalc_wtns = parse_bigints_to_witness(wtns)?;
Ok(witnesscalc_wtns)
}
#[test]
fn test_prove_rapidsnark() -> Result<()> {
// Create a new MoproCircom instance
let zkey_path = "./test-vectors/multiplier2_final.zkey".to_string();
let mut inputs = HashMap::new();
let a = BigInt::from_str(
"21888242871839275222246405745257275088548364400416034343698204186575808495616",
)
.unwrap();
let b = BigInt::from(1u8);
inputs.insert("a".to_string(), vec![a.to_string()]);
inputs.insert("b".to_string(), vec![b.to_string()]);
// Generate Witness Buffer
let wtns_buffer = compute_witness(inputs, multiplier2_witness)?;
// Generate Proof
let proof_result =
rust_rapidsnark::groth16_prover_zkey_file_wrapper(&zkey_path, wtns_buffer)?;
let vkey = std::fs::read_to_string("./test-vectors/multiplier2.vkey.json")?;
let valid = rust_rapidsnark::groth16_verify_wrapper(
&proof_result.proof,
&proof_result.public_signals,
&vkey,
)?;
assert!(valid);
Ok(())
}
#[test]
fn test_prove_rapidsnark_keccak() -> Result<()> {
// Create a new MoproCircom instance
let zkey_path = "./test-vectors/keccak256_256_test_final.zkey".to_string();
// Prepare inputs
let input_vec = vec![
116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
];
let inputs = bytes_to_circuit_inputs(&input_vec);
// Generate Witness Buffer
let wtns_buffer = compute_witness(inputs, keccak256256test_witness)?;
let wtns_data = std::fs::read("./test-vectors/keccak256_256_test.wtns")?;
assert_eq!(wtns_buffer, wtns_data);
// Generate Proof
let proof_result =
rust_rapidsnark::groth16_prover_zkey_file_wrapper(&zkey_path, wtns_buffer)?;
let vkey = std::fs::read_to_string("./test-vectors/keccak256_256_test.vkey.json")?;
let valid = rust_rapidsnark::groth16_verify_wrapper(
&proof_result.proof,
&proof_result.public_signals,
&vkey,
)?;
assert!(valid);
Ok(())
}
}