mirror of
https://github.com/logos-blockchain/logos-blockchain-rust-rapidsnark.git
synced 2026-06-07 03:39:29 +00:00
initial commit
This commit is contained in:
commit
a261813f77
43
.github/workflows/build-and-test.yml
vendored
Normal file
43
.github/workflows/build-and-test.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
- ready_for_review
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
clippy_check:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUSTFLAGS: "-Dwarnings" # Make sure CI fails on all warnings, including Clippy lints
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run Clippy
|
||||
run: cargo clippy --all-targets --all-features
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
- name: Run tests
|
||||
run: cargo test
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/target
|
||||
.DS_Store
|
||||
*.tmp
|
||||
*.swp
|
||||
2530
Cargo.lock
generated
Normal file
2530
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "rust-rapidsnark"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.95"
|
||||
ark-bn254 = "0.4.0"
|
||||
ark-circom = { git = "https://github.com/zkmopro/circom-compat.git", version = "0.1.0", branch = "wasm-delete" }
|
||||
num-bigint = "0.4.6"
|
||||
rust-witness = "0.1.2"
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.135"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
rust-witness = "0.1.2"
|
||||
42
build.rs
Normal file
42
build.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
// #[cfg(test)]
|
||||
rust_witness::transpile::transpile_wasm("./test-vectors".to_string());
|
||||
|
||||
let target = std::env::var("TARGET").unwrap();
|
||||
let arch = target.split('-').next().unwrap();
|
||||
|
||||
// Try to list contents of the target directory
|
||||
let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
let rapidsnark_dir = manifest_dir.join("rapidsnark");
|
||||
let absolute_lib_path = if rapidsnark_dir.join(&target).exists() {
|
||||
rapidsnark_dir.join(&target)
|
||||
} else {
|
||||
rapidsnark_dir.join(arch)
|
||||
};
|
||||
|
||||
let compiler = cc::Build::new().get_compiler();
|
||||
let cpp_stdlib = if compiler.is_like_clang() {
|
||||
"c++"
|
||||
} else {
|
||||
"stdc++"
|
||||
};
|
||||
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
absolute_lib_path.clone().display()
|
||||
);
|
||||
|
||||
println!("cargo:rustc-link-lib=static=rapidsnark");
|
||||
println!("cargo:rustc-link-lib={}", cpp_stdlib);
|
||||
if target.contains("android") {
|
||||
// pthread is included in libc in android
|
||||
println!("cargo:rustc-link-lib=c");
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib=pthread");
|
||||
}
|
||||
println!("cargo:rustc-link-lib=static=fr");
|
||||
println!("cargo:rustc-link-lib=static=fq");
|
||||
println!("cargo:rustc-link-lib=static=gmp");
|
||||
}
|
||||
3
rapidsnark/README.md
Normal file
3
rapidsnark/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
Built from [here](https://github.com/chancehudson/rapidsnark/tree/rust-ffi). This is built into static libraries and then linked into the rust project. Importantly we need to compile static libraries for each platform we intend to support.
|
||||
|
||||
Linking static libraries instead of compiling from c++ source should make it easier to maintain the `build.rs` script.
|
||||
BIN
rapidsnark/aarch64-apple-darwin/libfq.a
Normal file
BIN
rapidsnark/aarch64-apple-darwin/libfq.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-darwin/libfr.a
Normal file
BIN
rapidsnark/aarch64-apple-darwin/libfr.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-darwin/libgmp.a
Normal file
BIN
rapidsnark/aarch64-apple-darwin/libgmp.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-darwin/librapidsnark.a
Normal file
BIN
rapidsnark/aarch64-apple-darwin/librapidsnark.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/libfq.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/libfq.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/libfq_fat.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/libfq_fat.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/libfr.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/libfr.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/libfr_fat.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/libfr_fat.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/libgmp.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/libgmp.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/libgmp_fat.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/libgmp_fat.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/librapidsnark.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/librapidsnark.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/librapidsnark_arm64.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/librapidsnark_arm64.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios-sim/librapidsnark_fat.a
Normal file
BIN
rapidsnark/aarch64-apple-ios-sim/librapidsnark_fat.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios/libfq.a
Normal file
BIN
rapidsnark/aarch64-apple-ios/libfq.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios/libfr.a
Normal file
BIN
rapidsnark/aarch64-apple-ios/libfr.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios/libgmp.a
Normal file
BIN
rapidsnark/aarch64-apple-ios/libgmp.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios/libgmp_fat.a
Normal file
BIN
rapidsnark/aarch64-apple-ios/libgmp_fat.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64-apple-ios/librapidsnark.a
Normal file
BIN
rapidsnark/aarch64-apple-ios/librapidsnark.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64/libfq.a
Normal file
BIN
rapidsnark/aarch64/libfq.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64/libfr.a
Normal file
BIN
rapidsnark/aarch64/libfr.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64/libgmp.a
Normal file
BIN
rapidsnark/aarch64/libgmp.a
Normal file
Binary file not shown.
BIN
rapidsnark/aarch64/librapidsnark.a
Normal file
BIN
rapidsnark/aarch64/librapidsnark.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64-apple-ios/libfq.a
Normal file
BIN
rapidsnark/x86_64-apple-ios/libfq.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64-apple-ios/libfr.a
Normal file
BIN
rapidsnark/x86_64-apple-ios/libfr.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64-apple-ios/libgmp.a
Normal file
BIN
rapidsnark/x86_64-apple-ios/libgmp.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64-apple-ios/libgmp_fat.a
Normal file
BIN
rapidsnark/x86_64-apple-ios/libgmp_fat.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64-apple-ios/librapidsnark.a
Normal file
BIN
rapidsnark/x86_64-apple-ios/librapidsnark.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64/libfq.a
Normal file
BIN
rapidsnark/x86_64/libfq.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64/libfr.a
Normal file
BIN
rapidsnark/x86_64/libfr.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64/libgmp.a
Normal file
BIN
rapidsnark/x86_64/libgmp.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64/librapidsnark-fr-fq.a
Normal file
BIN
rapidsnark/x86_64/librapidsnark-fr-fq.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64/librapidsnark.a
Normal file
BIN
rapidsnark/x86_64/librapidsnark.a
Normal file
Binary file not shown.
BIN
rapidsnark/x86_64/librapidsnark.so
Normal file
BIN
rapidsnark/x86_64/librapidsnark.so
Normal file
Binary file not shown.
13
scripts/rapidsnark_build_dir.sh
Normal file
13
scripts/rapidsnark_build_dir.sh
Normal file
@ -0,0 +1,13 @@
|
||||
#!/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
|
||||
236
src/lib.rs
Normal file
236
src/lib.rs
Normal file
@ -0,0 +1,236 @@
|
||||
use std::ffi::CString;
|
||||
use std::fs::File;
|
||||
use std::os::raw::c_char;
|
||||
use std::os::raw::c_uint;
|
||||
use std::str::FromStr;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use ark_bn254::Bn254;
|
||||
use ark_circom::read_proving_key;
|
||||
use ark_circom::ZkeyHeaderReader;
|
||||
use num_bigint::BigInt;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
pub type WtnsFn = fn(HashMap<String, Vec<BigInt>>) -> Vec<BigInt>;
|
||||
|
||||
// match what rapidsnark expects
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[allow(non_snake_case)]
|
||||
struct VerificationKey {
|
||||
protocol: String,
|
||||
curve: String,
|
||||
nPublic: u32,
|
||||
vk_alpha_1: [String; 3],
|
||||
vk_beta_2: [[String; 2]; 3],
|
||||
vk_gamma_2: [[String; 2]; 3],
|
||||
vk_delta_2: [[String; 2]; 3],
|
||||
IC: Vec<[String; 3]>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ProofResult {
|
||||
proof: *mut c_char,
|
||||
public_signals: *mut c_char,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn groth16_api_prove(
|
||||
zkeyFilename: *const c_char,
|
||||
wtnsData: *mut u8,
|
||||
wtnsDataLen: c_uint,
|
||||
) -> *mut ProofResult;
|
||||
fn groth16_api_verify(proof: *mut ProofResult, key_json: *const c_char) -> bool;
|
||||
fn free_proof_result(result: *mut ProofResult);
|
||||
}
|
||||
|
||||
pub fn verify_proof(zkey_path: &str, proof: String) -> Result<bool> {
|
||||
let mut header_reader = ZkeyHeaderReader::new(zkey_path);
|
||||
header_reader.read();
|
||||
let file = File::open(zkey_path)?;
|
||||
let mut reader = std::io::BufReader::new(file);
|
||||
let proving_key = read_proving_key::<_, Bn254>(&mut reader)?;
|
||||
// convert out proving key to json so we can
|
||||
// use it with rapidsnark
|
||||
let vk = proving_key.vk;
|
||||
// let v = proving_key.vk.alpha_g1.to_string();
|
||||
let vkey = VerificationKey {
|
||||
protocol: "groth16".to_string(),
|
||||
curve: "bn128".to_string(),
|
||||
nPublic: 0, // this is unused in the rapidsnark verifier
|
||||
vk_alpha_1: [
|
||||
vk.alpha_g1.x.to_string(),
|
||||
vk.alpha_g1.y.to_string(),
|
||||
"1".to_string(),
|
||||
],
|
||||
vk_beta_2: [
|
||||
[vk.beta_g2.x.c0.to_string(), vk.beta_g2.x.c1.to_string()],
|
||||
[vk.beta_g2.y.c0.to_string(), vk.beta_g2.y.c1.to_string()],
|
||||
["1".to_string(), "0".to_string()],
|
||||
],
|
||||
vk_gamma_2: [
|
||||
[vk.gamma_g2.x.c0.to_string(), vk.gamma_g2.x.c1.to_string()],
|
||||
[vk.gamma_g2.y.c0.to_string(), vk.gamma_g2.y.c1.to_string()],
|
||||
["1".to_string(), "0".to_string()],
|
||||
],
|
||||
vk_delta_2: [
|
||||
[vk.delta_g2.x.c0.to_string(), vk.delta_g2.x.c1.to_string()],
|
||||
[vk.delta_g2.y.c0.to_string(), vk.delta_g2.y.c1.to_string()],
|
||||
["1".to_string(), "0".to_string()],
|
||||
],
|
||||
IC: vk
|
||||
.gamma_abc_g1
|
||||
.iter()
|
||||
.map(|p| [p.x.to_string(), p.y.to_string(), "1".to_string()])
|
||||
.collect(),
|
||||
};
|
||||
let vkey_json = serde_json::to_string(&vkey)?;
|
||||
let vkey_json_cstr = CString::new(vkey_json)?;
|
||||
let v: serde_json::Value = serde_json::from_str(&proof)?;
|
||||
let proof = v["proof"].to_string();
|
||||
let signals = v["signals"].to_string();
|
||||
unsafe {
|
||||
let result = groth16_api_verify(
|
||||
&mut ProofResult {
|
||||
proof: CString::new(proof).unwrap().into_raw(),
|
||||
public_signals: CString::new(signals).unwrap().into_raw(),
|
||||
},
|
||||
vkey_json_cstr.as_ptr(),
|
||||
);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_proof(
|
||||
zkey_path: &str,
|
||||
inputs: std::collections::HashMap<String, Vec<String>>,
|
||||
witness_fn: WtnsFn,
|
||||
) -> Result<String> {
|
||||
// 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 mut wtns = witness_fn(bigint_inputs)
|
||||
.into_iter()
|
||||
.map(|w| w.to_biguint().unwrap())
|
||||
.flat_map(|v| {
|
||||
let mut bytes = v.to_bytes_le();
|
||||
bytes.resize(32, 0);
|
||||
bytes
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Convert Rust strings to C strings
|
||||
let zkey_cstr = CString::new(zkey_path).context("Failed to create CString for zkey path")?;
|
||||
|
||||
unsafe {
|
||||
let proof_ptr =
|
||||
groth16_api_prove(zkey_cstr.as_ptr(), wtns.as_mut_ptr(), wtns.len() as c_uint);
|
||||
|
||||
if proof_ptr.is_null() {
|
||||
return Err(anyhow::anyhow!("Proof generation failed"));
|
||||
}
|
||||
|
||||
// Convert both strings
|
||||
let result = &*proof_ptr;
|
||||
let proof = std::ffi::CStr::from_ptr(result.proof)
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
let public_signals = std::ffi::CStr::from_ptr(result.public_signals)
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
free_proof_result(proof_ptr);
|
||||
Ok(format!(
|
||||
"{{ \"proof\": {proof},\"signals\": {public_signals}}}"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::HashMap;
|
||||
use num_bigint::BigInt;
|
||||
use std::str::FromStr;
|
||||
use anyhow::Result;
|
||||
use anyhow::bail;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#[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);
|
||||
// let c = a.clone() * b.clone();
|
||||
inputs.insert("a".to_string(), vec![a.to_string()]);
|
||||
inputs.insert("b".to_string(), vec![b.to_string()]);
|
||||
|
||||
let proof_json = super::generate_proof(&zkey_path, inputs, multiplier2_witness)?;
|
||||
let valid = super::verify_proof(&zkey_path, proof_json)?;
|
||||
if !valid {
|
||||
bail!("Proof is invalid");
|
||||
}
|
||||
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 Proof
|
||||
let proof_json = super::generate_proof(&zkey_path, inputs, keccak256256test_witness)?;
|
||||
let valid = super::verify_proof(&zkey_path, proof_json)?;
|
||||
if !valid {
|
||||
bail!("Proof is invalid");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
BIN
test-vectors/keccak256_256_test.wasm
Normal file
BIN
test-vectors/keccak256_256_test.wasm
Normal file
Binary file not shown.
BIN
test-vectors/keccak256_256_test_final.zkey
Normal file
BIN
test-vectors/keccak256_256_test_final.zkey
Normal file
Binary file not shown.
BIN
test-vectors/multiplier2.r1cs
Normal file
BIN
test-vectors/multiplier2.r1cs
Normal file
Binary file not shown.
BIN
test-vectors/multiplier2.wasm
Normal file
BIN
test-vectors/multiplier2.wasm
Normal file
Binary file not shown.
BIN
test-vectors/multiplier2_bls.wasm
Normal file
BIN
test-vectors/multiplier2_bls.wasm
Normal file
Binary file not shown.
BIN
test-vectors/multiplier2_bls_final.zkey
Normal file
BIN
test-vectors/multiplier2_bls_final.zkey
Normal file
Binary file not shown.
BIN
test-vectors/multiplier2_final.zkey
Normal file
BIN
test-vectors/multiplier2_final.zkey
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user