Skip to content

Commit 845f822

Browse files
authored
Test/adding testing fo witnesscalc (#343)
* refine rust_witness testing * unify the witness type to String * test: adding a witnesscalc test case * cleanup * upload testing data * toml: adding feature to control circom features * fix inputs type * fix udl * fix the input type of generateCircomProof in swift and kt files * cleanup and adding comment * define features in mopro-ffi codebase to avoid unexpected compliation error * using witnesscalc_adapter::build_and_link * fix: review feedback * rename cfg features * removed un-necessary deps. in test-e2e
1 parent 31959b1 commit 845f822

File tree

22 files changed

+540
-345
lines changed

22 files changed

+540
-345
lines changed

Cargo.lock

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

circom-prover/Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ exclude = ["test-vectors/*"]
1111

1212
[lib]
1313
name = "circom_prover"
14-
14+
1515
[features]
1616
default = ["rustwitness", "arkworks", "ethereum"]
1717

@@ -34,7 +34,6 @@ arkworks = [
3434
]
3535
rapidsnark = [
3636
"rust-rapidsnark",
37-
"serde_json",
3837
"ark-bn254",
3938
"ark-ec",
4039
"ark-groth16",
@@ -55,6 +54,7 @@ anyhow = "1.0.95"
5554
rust-witness = { version = "0.1", optional = true }
5655
byteorder = { version = "1.0.0" }
5756
uuid = { version = "1.9.1", features = ["v4"] }
57+
serde_json = "1.0.94"
5858

5959
# arkworks
6060
ark-ec = { version = "=0.4.1", default-features = false, features = [
@@ -85,7 +85,7 @@ witnesscalc-adapter = { version = "0.1.0", optional = true }
8585

8686
# rapidsnark
8787
rust-rapidsnark = { version = "0.1.0", optional = true }
88-
serde_json = { version = "1.0.94", optional = true }
88+
8989

9090
# ethereum
9191
rayon = { version = "1.10.0" }
@@ -100,5 +100,4 @@ witnesscalc-adapter = { version = "0.1.0", optional = true }
100100
rust-rapidsnark = { version = "0.1.0", optional = true }
101101

102102
[dev-dependencies]
103-
serde_json = "1.0.94"
104103
hex-literal = "0.4.1"

circom-prover/src/lib.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ pub mod witness;
33

44
use anyhow::Result;
55
use prover::{CircomProof, ProofLib};
6-
use std::collections::HashMap;
76

87
#[cfg(feature = "rapidsnark")]
98
pub use prover::rapidsnark;
@@ -20,10 +19,10 @@ impl CircomProver {
2019
pub fn prove(
2120
proof_lib: ProofLib,
2221
wit_fn: WitnessFn,
23-
inputs: HashMap<String, Vec<String>>,
22+
json_input_str: String,
2423
zkey_path: String,
2524
) -> Result<CircomProof> {
26-
let wit_thread = witness::generate_witness(wit_fn, inputs);
25+
let wit_thread = witness::generate_witness(wit_fn, json_input_str);
2726
prover::prove(proof_lib, zkey_path.clone(), wit_thread)
2827
}
2928

@@ -39,6 +38,8 @@ impl CircomProver {
3938

4039
#[cfg(test)]
4140
mod tests {
41+
use std::collections::HashMap;
42+
4243
use super::*;
4344
const ZKEY_PATH: &str = "./test-vectors/multiplier2_final.zkey";
4445

@@ -47,7 +48,8 @@ mod tests {
4748
("a".to_string(), vec!["1".to_string()]),
4849
("b".to_string(), vec!["2".to_string()]),
4950
]);
50-
CircomProver::prove(proof_lib, witness_fn, inputs, ZKEY_PATH.to_string()).unwrap()
51+
let input_str = serde_json::to_string(&inputs).unwrap();
52+
CircomProver::prove(proof_lib, witness_fn, input_str, ZKEY_PATH.to_string()).unwrap()
5153
}
5254

5355
fn verify_proof(proof: Vec<u8>, public_inputs: Vec<u8>, proof_lib: ProofLib) -> bool {
@@ -69,21 +71,9 @@ mod tests {
6971
#[cfg(all(feature = "witnesscalc", feature = "arkworks"))]
7072
#[test]
7173
fn test_witnesscalc_arkworks_prove_and_verify() {
72-
use num_bigint::BigInt;
7374
witnesscalc_adapter::witness!(multiplier2);
74-
// TODO: The conversion should be exported in witness.rs https://github.com/zkmopro/mopro/issues/331
75-
fn create_multiplier2_witness(inputs: HashMap<String, Vec<BigInt>>) -> Vec<BigInt> {
76-
let inputs_str: HashMap<String, Vec<String>> = inputs
77-
.into_iter()
78-
.map(|(k, v)| (k, v.into_iter().map(|i| i.to_string()).collect()))
79-
.collect();
80-
let wtns =
81-
multiplier2_witness(&witnesscalc_adapter::convert_inputs_to_json(inputs_str))
82-
.unwrap();
83-
witnesscalc_adapter::parse_witness_to_bigints(&wtns).unwrap()
84-
}
8575
let res = generate_proof(
86-
WitnessFn::WitnessCalc(create_multiplier2_witness),
76+
WitnessFn::WitnessCalc(multiplier2_witness),
8777
ProofLib::Arkworks,
8878
);
8979
let res = verify_proof(res.proof, res.pub_inputs, ProofLib::Arkworks);

circom-prover/src/witness.rs

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
use num::{BigInt, BigUint};
22
use std::{collections::HashMap, str::FromStr, thread::JoinHandle};
33

4+
#[cfg(feature = "witnesscalc")]
5+
use witnesscalc_adapter::parse_witness_to_bigints;
6+
47
/// Witness function signature for rust_witness (inputs) -> witness
58
#[cfg(feature = "rustwitness")]
69
type RustWitnessWtnsFn = fn(HashMap<String, Vec<BigInt>>) -> Vec<BigInt>;
710
/// Witness function signature for witnesscalc_adapter (inputs) -> witness
811
#[cfg(feature = "witnesscalc")]
9-
type WitnesscalcWtnsFn = fn(HashMap<String, Vec<BigInt>>) -> Vec<BigInt>;
12+
type WitnesscalcWtnsFn = fn(&str) -> anyhow::Result<Vec<u8>>;
1013

1114
#[derive(Debug, Clone, Copy)]
1215
pub enum WitnessFn {
@@ -16,32 +19,59 @@ pub enum WitnessFn {
1619
RustWitness(RustWitnessWtnsFn),
1720
}
1821

19-
pub fn generate_witness(
20-
witness_fn: WitnessFn,
21-
inputs: HashMap<String, Vec<String>>,
22-
) -> JoinHandle<Vec<BigUint>> {
23-
std::thread::spawn(move || {
24-
let bigint_inputs = inputs
25-
.into_iter()
26-
.map(|(k, v)| {
27-
(
28-
k,
29-
v.into_iter()
30-
.map(|i| BigInt::from_str(&i).unwrap())
31-
.collect(),
32-
)
33-
})
34-
.collect();
22+
pub fn generate_witness(witness_fn: WitnessFn, json_input_str: String) -> JoinHandle<Vec<BigUint>> {
23+
#[cfg(feature = "rustwitness")]
24+
let witness_map = json_to_hashmap(json_input_str.as_str()).unwrap();
3525

26+
std::thread::spawn(move || {
3627
let witness = match witness_fn {
3728
#[cfg(feature = "witnesscalc")]
38-
WitnessFn::WitnessCalc(wit_fn) => wit_fn(bigint_inputs),
29+
WitnessFn::WitnessCalc(wit_fn) => {
30+
let witness = wit_fn(json_input_str.as_str()).unwrap();
31+
parse_witness_to_bigints(&witness).unwrap()
32+
}
3933
#[cfg(feature = "rustwitness")]
40-
WitnessFn::RustWitness(wit_fn) => wit_fn(bigint_inputs),
34+
WitnessFn::RustWitness(wit_fn) => {
35+
let bigint_inputs = witness_map
36+
.into_iter()
37+
.map(|(k, v)| {
38+
(
39+
k,
40+
v.into_iter()
41+
.map(|i| BigInt::from_str(&i).unwrap())
42+
.collect(),
43+
)
44+
})
45+
.collect();
46+
wit_fn(bigint_inputs)
47+
}
4148
};
4249
witness
4350
.into_iter()
4451
.map(|w| w.to_biguint().unwrap())
4552
.collect::<Vec<_>>()
4653
})
4754
}
55+
56+
#[cfg(feature = "rustwitness")]
57+
pub fn json_to_hashmap(json_str: &str) -> Result<HashMap<String, Vec<String>>, serde_json::Error> {
58+
use serde_json::Value;
59+
60+
let value: Value = serde_json::from_str(json_str)?;
61+
62+
let mut hashmap = HashMap::new();
63+
64+
if let Value::Object(map) = value {
65+
for (key, val) in map {
66+
if let Value::Array(arr) = val {
67+
let vec: Vec<String> = arr
68+
.into_iter()
69+
.filter_map(|v| v.as_str().map(|s| s.to_string()))
70+
.collect();
71+
hashmap.insert(key, vec);
72+
}
73+
}
74+
}
75+
76+
Ok(hashmap)
77+
}

cli/src/template/android/app/src/main/java/com/example/moproapp/MultiplierComponent.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fun MultiplierComponent() {
3939
Thread(
4040
Runnable {
4141
val startTime = System.currentTimeMillis()
42-
res = generateCircomProof(zkeyPath, inputs)
42+
res = generateCircomProof(zkeyPath, inputs.toString())
4343
val endTime = System.currentTimeMillis()
4444
provingTime = "proving time: " + (endTime - startTime).toString() + " ms"
4545
}

cli/src/template/ios/MoproApp/ContentView.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,19 @@ extension ContentView {
7272
textViewText += "Generating Circom proof... "
7373
do {
7474
// Prepare inputs
75-
var inputs = [String: [String]]()
7675
let a = 3
7776
let b = 5
7877
let c = a*b
79-
inputs["a"] = [String(a)]
80-
inputs["b"] = [String(b)]
81-
78+
let input_str: String = "{\"b\":[\"5\"],\"a\":[\"3\"]}"
79+
8280
// Expected outputs
8381
let outputs: [String] = [String(c), String(a)]
8482
let expectedOutput: [UInt8] = serializeOutputs(outputs)
8583

8684
let start = CFAbsoluteTimeGetCurrent()
8785

8886
// Generate Proof
89-
let generateProofResult = try generateCircomProof(zkeyPath: zkeyPath, circuitInputs: inputs)
87+
let generateProofResult = try generateCircomProof(zkeyPath: zkeyPath, circuitInputs: input_str)
9088
assert(!generateProofResult.proof.isEmpty, "Proof should not be empty")
9189
assert(Data(expectedOutput) == generateProofResult.inputs, "Circuit outputs mismatch the expected outputs")
9290

mopro-ffi/Cargo.toml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,25 @@ default = []
1717

1818
halo2 = []
1919
circom = [
20-
"circom-prover",
21-
"rust-witness",
20+
"rustwitness",
21+
"arkworks",
2222
"ark-bn254",
2323
"ark-bls12-381",
2424
"ark-ff",
2525
]
2626

27+
# circom features
28+
## witness
29+
rustwitness = ["circom-prover/rustwitness", "rust-witness"]
30+
witnesscalc = ["circom-prover/witnesscalc", "witnesscalc-adapter"]
31+
## proof
32+
arkworks = ["circom-prover/arkworks"]
33+
rapidsnark = ["circom-prover/rapidsnark"]
34+
## include all circom features
35+
circom-all = ["rustwitness", "witnesscalc", "arkworks", "rapidsnark"]
36+
37+
38+
2739
[dependencies]
2840
uniffi = { version = "=0.28.0", features = ["cli", "build"] }
2941
serde = { version = "1.0", features = ["derive"] }
@@ -39,8 +51,9 @@ color-eyre = "=0.6.2"
3951

4052
# circom deps
4153
rust-witness = { version = "0.1", optional = true }
54+
witnesscalc-adapter = { version = "0.1", optional = true }
4255
ark-ff = { version = "0.4.0", optional = true }
43-
circom-prover = { path = "../circom-prover", optional = true }
56+
circom-prover = { path = "../circom-prover", optional = true}
4457

4558
# ZKP generation
4659
ark-bn254 = { version = "=0.4.0", optional = true }
@@ -49,12 +62,14 @@ ark-bls12-381 = { version = "0.4.0", optional = true }
4962

5063
[build-dependencies]
5164
rust-witness = { version = "0.1", optional = true }
65+
witnesscalc-adapter = { version = "0.1", optional = true }
5266
uniffi = { version = "=0.28.0", features = ["build"] }
5367

5468
[dev-dependencies]
5569
color-eyre = "0.6"
5670
serde = { version = "1.0", features = ["derive"] }
5771
serde_derive = "1.0"
72+
serde_json = "1.0.94"
5873

5974
# Halo2 dependencies
6075
plonk-fibonacci = { workspace = true }

mopro-ffi/build.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
fn main() {
22
#[cfg(feature = "circom")]
3-
if std::env::var("MOPRO_FFI_LINK_TEST_WITNESS").unwrap_or_default() != "" {
4-
rust_witness::transpile::transpile_wasm("../test-vectors/circom".to_string());
3+
{
4+
if std::env::var("MOPRO_FFI_LINK_TEST_WITNESS").unwrap_or_default() != "" {
5+
#[cfg(feature = "rustwitness")]
6+
rust_witness::transpile::transpile_wasm("../test-vectors/circom".to_string());
7+
8+
#[cfg(feature = "witnesscalc")]
9+
witnesscalc_adapter::build_and_link("../test-vectors/circom/witnesscalc");
10+
}
511
}
612
}

0 commit comments

Comments
 (0)