diff --git a/circom-prover/src/lib.rs b/circom-prover/src/lib.rs index 467ae183e..1eb16c6b1 100644 --- a/circom-prover/src/lib.rs +++ b/circom-prover/src/lib.rs @@ -72,6 +72,21 @@ mod tests { assert!(verify_proof(proof, ProofLib::Arkworks)); } + #[cfg(all(feature = "rustwitness", feature = "arkworks"))] + #[test] + fn test_rustwitness_arkworks_bls12_381_prove_and_verify() { + rust_witness::witness!(mux); + let inputs = HashMap::from([("in".to_string(), vec!["42".to_string()])]); + let zkey_path = "./test-vectors/mux.zkey"; + let input_str = serde_json::to_string(&inputs).unwrap(); + let proof_lib = ProofLib::Arkworks; + let witness_fn = WitnessFn::RustWitness(mux_witness); + let proof = + CircomProver::prove(proof_lib, witness_fn, input_str, zkey_path.to_string()).unwrap(); + let valid = CircomProver::verify(proof_lib, proof, zkey_path.to_string()).unwrap(); + assert!(valid); + } + #[cfg(all(feature = "witnesscalc", feature = "arkworks"))] #[test] fn test_witnesscalc_arkworks_prove_and_verify() { diff --git a/circom-prover/src/prover/ark_circom/qap.rs b/circom-prover/src/prover/ark_circom/qap.rs index 1950de875..1f32d46d9 100644 --- a/circom-prover/src/prover/ark_circom/qap.rs +++ b/circom-prover/src/prover/ark_circom/qap.rs @@ -61,32 +61,76 @@ impl R1CSToQAP for CircomReduction { *c_i = a * b; }); - domain.ifft_in_place(&mut a); - domain.ifft_in_place(&mut b); - - let root_of_unity = { - let domain_size_double = 2 * domain_size; - let domain_double = - D::new(domain_size_double).ok_or(SynthesisError::PolynomialDegreeTooLarge)?; - domain_double.element(1) + let s = F::TWO_ADICITY as u64; + let power = ark_std::log2(domain_size) as u64; + let k: u64 = if s == 32 { 5 } else { 1 }; + + // Get snarkjs-compatible generator for this domain size + let snarkjs_omega = { + let exp = 1u64 << (s - power); + F::TWO_ADIC_ROOT_OF_UNITY.pow([k]).pow([exp]) }; - D::distribute_powers_and_mul_by_const(&mut a, root_of_unity, F::one()); - D::distribute_powers_and_mul_by_const(&mut b, root_of_unity, F::one()); + let snarkjs_omega_inv = snarkjs_omega.inverse().unwrap(); - domain.fft_in_place(&mut a); - domain.fft_in_place(&mut b); + // Coset shift = snarkjs w[power+1] + let inc = { + let exp = 1u64 << (s - power - 1); + F::TWO_ADIC_ROOT_OF_UNITY.pow([k]).pow([exp]) + }; + + if k != 1 { + // Use manual DFT with snarkjs's roots + let n_inv = F::from(domain_size as u64).inverse().unwrap(); + + manual_ifft(&mut a, snarkjs_omega_inv, n_inv, domain_size); + manual_ifft(&mut b, snarkjs_omega_inv, n_inv, domain_size); + + apply_powers(&mut a, inc); + apply_powers(&mut b, inc); + + manual_fft(&mut a, snarkjs_omega, domain_size); + manual_fft(&mut b, snarkjs_omega, domain_size); + + let mut ab: Vec = a.iter().zip(&b).map(|(&ai, &bi)| ai * bi).collect(); + + manual_ifft(&mut c, snarkjs_omega_inv, n_inv, domain_size); + apply_powers(&mut c, inc); + manual_fft(&mut c, snarkjs_omega, domain_size); + + ab.par_iter_mut() + .zip(c) + .for_each(|(ab_i, c_i)| *ab_i -= &c_i); - let mut ab = domain.mul_polynomials_in_evaluation_domain(&a, &b); + Ok(ab) + } else { + // BN254: use arkworks FFT as before (original CircomReduction logic) + domain.ifft_in_place(&mut a); + domain.ifft_in_place(&mut b); - domain.ifft_in_place(&mut c); - D::distribute_powers_and_mul_by_const(&mut c, root_of_unity, F::one()); - domain.fft_in_place(&mut c); + let root_of_unity = { + let domain_double = + D::new(2 * domain_size).ok_or(SynthesisError::PolynomialDegreeTooLarge)?; + domain_double.element(1) + }; - ab.par_iter_mut() - .zip(c) - .for_each(|(ab_i, c_i)| *ab_i -= &c_i); + D::distribute_powers_and_mul_by_const(&mut a, root_of_unity, F::one()); + D::distribute_powers_and_mul_by_const(&mut b, root_of_unity, F::one()); - Ok(ab) + domain.fft_in_place(&mut a); + domain.fft_in_place(&mut b); + + let mut ab = domain.mul_polynomials_in_evaluation_domain(&a, &b); + + domain.ifft_in_place(&mut c); + D::distribute_powers_and_mul_by_const(&mut c, root_of_unity, F::one()); + domain.fft_in_place(&mut c); + + ab.par_iter_mut() + .zip(c) + .for_each(|(ab_i, c_i)| *ab_i -= &c_i); + + Ok(ab) + } } fn h_query_scalars>( @@ -107,3 +151,61 @@ impl R1CSToQAP for CircomReduction { Ok(scalars.into_par_iter().skip(1).step_by(2).collect()) } } + +fn manual_fft(vals: &mut Vec, omega: F, n: usize) { + let log_n = ark_std::log2(n) as usize; + + // Bit-reverse permutation + for i in 0..n { + let j = bit_reverse(i, log_n); + if i < j { + vals.swap(i, j); + } + } + + // Cooley-Tukey + let mut len = 2; + while len <= n { + let half = len / 2; + let step = n / len; + // omega_len = omega^step = primitive len-th root + let omega_len = omega.pow([step as u64]); + + for start in (0..n).step_by(len) { + let mut w = F::one(); + for j in 0..half { + let u = vals[start + j]; + let v = vals[start + j + half] * w; + vals[start + j] = u + v; + vals[start + j + half] = u - v; + w *= omega_len; + } + } + len <<= 1; + } +} + +fn manual_ifft(vals: &mut Vec, omega_inv: F, n_inv: F, n: usize) { + manual_fft(vals, omega_inv, n); + // Scale by 1/n + for v in vals.iter_mut() { + *v *= n_inv; + } +} + +fn apply_powers(vals: &mut Vec, base: F) { + let mut pow = F::one(); + for v in vals.iter_mut() { + *v *= pow; + pow *= base; + } +} + +fn bit_reverse(mut x: usize, log_n: usize) -> usize { + let mut result = 0; + for _ in 0..log_n { + result = (result << 1) | (x & 1); + x >>= 1; + } + result +} diff --git a/circom-prover/test-vectors/multiplexer.wasm b/circom-prover/test-vectors/multiplexer.wasm new file mode 100644 index 000000000..7b159e69b Binary files /dev/null and b/circom-prover/test-vectors/multiplexer.wasm differ diff --git a/circom-prover/test-vectors/multiplexer_final.zkey b/circom-prover/test-vectors/multiplexer_final.zkey new file mode 100644 index 000000000..0ddbae8b4 Binary files /dev/null and b/circom-prover/test-vectors/multiplexer_final.zkey differ diff --git a/circom-prover/test-vectors/multiplier2_bls.wasm b/circom-prover/test-vectors/multiplier2_bls.wasm new file mode 100644 index 000000000..e3ec0b39b Binary files /dev/null and b/circom-prover/test-vectors/multiplier2_bls.wasm differ diff --git a/circom-prover/test-vectors/mux.wasm b/circom-prover/test-vectors/mux.wasm new file mode 100644 index 000000000..5a8b8dd05 Binary files /dev/null and b/circom-prover/test-vectors/mux.wasm differ diff --git a/circom-prover/test-vectors/mux.zkey b/circom-prover/test-vectors/mux.zkey new file mode 100644 index 000000000..b574ad900 Binary files /dev/null and b/circom-prover/test-vectors/mux.zkey differ diff --git a/circom/.gitignore b/circom/.gitignore new file mode 100644 index 000000000..466e24805 --- /dev/null +++ b/circom/.gitignore @@ -0,0 +1 @@ +out/ \ No newline at end of file diff --git a/circom/circuits/multiplexer.circom b/circom/circuits/multiplexer.circom new file mode 100644 index 000000000..34bca9826 --- /dev/null +++ b/circom/circuits/multiplexer.circom @@ -0,0 +1,10 @@ +pragma circom 2.1.9; + +template Demo() { + signal input in; + signal output out; + + signal x <-- 1; + out <== in * x; +} +component main = Demo(); \ No newline at end of file diff --git a/circom/circuits/mux.circom b/circom/circuits/mux.circom new file mode 100644 index 000000000..afbba01d4 --- /dev/null +++ b/circom/circuits/mux.circom @@ -0,0 +1,15 @@ +pragma circom 2.2.3; + +include "circomlib/circuits/multiplexer.circom"; + +template Demo { + signal input in; + signal output out; + + component dotCheck = Multiplexer(1,2); + dotCheck.inp[0][0] <== 0; + dotCheck.inp[1][0] <== in; + dotCheck.sel <== 1; + dotCheck.out[0] ==> out; +} +component main = Demo(); \ No newline at end of file diff --git a/circom/input_mux.json b/circom/input_mux.json new file mode 100644 index 000000000..9aa255591 --- /dev/null +++ b/circom/input_mux.json @@ -0,0 +1,3 @@ +{ + "in": 42 +} diff --git a/circom/package-lock.json b/circom/package-lock.json new file mode 100644 index 000000000..b101da22a --- /dev/null +++ b/circom/package-lock.json @@ -0,0 +1,385 @@ +{ + "name": "circom-circuits", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "circom-circuits", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "circomlib": "^2.0.5", + "snarkjs": "^0.7.6" + } + }, + "node_modules/@iden3/bigarray": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@iden3/bigarray/-/bigarray-0.0.2.tgz", + "integrity": "sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g==", + "license": "GPL-3.0" + }, + "node_modules/@iden3/binfileutils": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.12.tgz", + "integrity": "sha512-naAmzuDufRIcoNfQ1d99d7hGHufLA3wZSibtr4dMe6ZeiOPV1KwOZWTJ1YVz4HbaWlpDuzVU72dS4ATQS4PXBQ==", + "license": "GPL-3.0", + "dependencies": { + "fastfile": "0.0.20", + "ffjavascript": "^0.3.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bfj": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", + "integrity": "sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==", + "license": "MIT", + "dependencies": { + "bluebird": "^3.7.2", + "check-types": "^11.2.3", + "hoopy": "^0.1.4", + "jsonpath": "^1.1.1", + "tryer": "^1.0.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", + "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/check-types": { + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", + "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==", + "license": "MIT" + }, + "node_modules/circom_runtime": { + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.28.tgz", + "integrity": "sha512-ACagpQ7zBRLKDl5xRZ4KpmYIcZDUjOiNRuxvXLqhnnlLSVY1Dbvh73TI853nqoR0oEbihtWmMSjgc5f+pXf/jQ==", + "license": "Apache-2.0", + "dependencies": { + "ffjavascript": "0.3.1" + }, + "bin": { + "calcwit": "calcwit.js" + } + }, + "node_modules/circomlib": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/circomlib/-/circomlib-2.0.5.tgz", + "integrity": "sha512-O7NQ8OS+J4eshBuoy36z/TwQU0YHw8W3zxZcs4hVwpEll3e4hDm3mgkIPqItN8FDeLEKZFK3YeT/+k8TiLF3/A==", + "license": "GPL-3.0" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fastfile": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.20.tgz", + "integrity": "sha512-r5ZDbgImvVWCP0lA/cGNgQcZqR+aYdFx3u+CtJqUE510pBUVGMn4ulL/iRTI4tACTYsNJ736uzFxEBXesPAktA==", + "license": "GPL-3.0" + }, + "node_modules/ffjavascript": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.1.tgz", + "integrity": "sha512-4PbK1WYodQtuF47D4pRI5KUg3Q392vuP5WjE1THSnceHdXwU3ijaoS0OqxTzLknCtz4Z2TtABzkBdBdMn3B/Aw==", + "license": "GPL-3.0", + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.5.tgz", + "integrity": "sha512-ct/ckWBV/9Dg3MlvCXsLcSUyoWwv9mCKqlhLNB2DAuXR/NZolSXlQqP5dyy6guWlPXBhodZyZ5lGPQcbQDxrEQ==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^10.2.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonpath": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.2.1.tgz", + "integrity": "sha512-Jl6Jhk0jG+kP3yk59SSeGq7LFPR4JQz1DU0K+kXTysUhMostbhU3qh5mjTuf0PqFcXpAT7kvmMt9WxV10NyIgQ==", + "license": "MIT", + "dependencies": { + "esprima": "1.2.5", + "static-eval": "2.1.1", + "underscore": "1.13.6" + } + }, + "node_modules/logplease": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.15.tgz", + "integrity": "sha512-jLlHnlsPSJjpwUfcNyUxXCl33AYg2cHhIf9QhGL2T4iPT0XPB+xP1LRKFPgIg1M/sg9kAJvy94w9CzBNrfnstA==", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", + "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/r1csfile": { + "version": "0.0.48", + "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.48.tgz", + "integrity": "sha512-kHRkKUJNaor31l05f2+RFzvcH5XSa7OfEfd/l4hzjte6NL6fjRkSMfZ4BjySW9wmfdwPOtq3mXurzPvPGEf5Tw==", + "license": "GPL-3.0", + "dependencies": { + "@iden3/bigarray": "0.0.2", + "@iden3/binfileutils": "0.0.12", + "fastfile": "0.0.20", + "ffjavascript": "0.3.0" + } + }, + "node_modules/r1csfile/node_modules/ffjavascript": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.3.0.tgz", + "integrity": "sha512-l7sR5kmU3gRwDy8g0Z2tYBXy5ttmafRPFOqY7S6af5cq51JqJWt5eQ/lSR/rs2wQNbDYaYlQr5O+OSUf/oMLoQ==", + "license": "GPL-3.0", + "dependencies": { + "wasmbuilder": "0.0.16", + "wasmcurves": "0.2.2", + "web-worker": "1.2.0" + } + }, + "node_modules/snarkjs": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.7.6.tgz", + "integrity": "sha512-4uH1xA5JzVU5jaaWS2fXej3+RC6L5Erhr6INTJtUA27du4Elbh4VXCeeRjB4QiwL6N6y7SNKePw5prTxyEf4Zg==", + "license": "GPL-3.0", + "dependencies": { + "@iden3/binfileutils": "0.0.12", + "@noble/hashes": "^1.7.1", + "bfj": "^7.0.2", + "circom_runtime": "0.1.28", + "ejs": "^3.1.6", + "fastfile": "0.0.20", + "ffjavascript": "0.3.1", + "logplease": "^1.2.15", + "r1csfile": "0.0.48" + }, + "bin": { + "snarkjs": "build/cli.cjs" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz", + "integrity": "sha512-MgWpQ/ZjGieSVB3eOJVs4OA2LT/q1vx98KPCTTQPzq/aLr0YUXTsgryTXr4SLfR0ZfUUCiedM9n/ABeDIyy4mA==", + "license": "MIT", + "dependencies": { + "escodegen": "^2.1.0" + } + }, + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "license": "MIT" + }, + "node_modules/wasmbuilder": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.16.tgz", + "integrity": "sha512-Qx3lEFqaVvp1cEYW7Bfi+ebRJrOiwz2Ieu7ZG2l7YyeSJIok/reEQCQCuicj/Y32ITIJuGIM9xZQppGx5LrQdA==", + "license": "GPL-3.0" + }, + "node_modules/wasmcurves": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.2.2.tgz", + "integrity": "sha512-JRY908NkmKjFl4ytnTu5ED6AwPD+8VJ9oc94kdq7h5bIwbj0L4TDJ69mG+2aLs2SoCmGfqIesMWTEJjtYsoQXQ==", + "license": "GPL-3.0", + "dependencies": { + "wasmbuilder": "0.0.16" + } + }, + "node_modules/web-worker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", + "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==", + "license": "Apache-2.0" + } + } +} diff --git a/circom/package.json b/circom/package.json new file mode 100644 index 000000000..29f61ca8e --- /dev/null +++ b/circom/package.json @@ -0,0 +1,16 @@ +{ + "name": "circom-circuits", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "sh scripts/build_circuits.sh" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "circomlib": "^2.0.5", + "snarkjs": "^0.7.6" + } +} diff --git a/circom/scripts/build_circuits.sh b/circom/scripts/build_circuits.sh new file mode 100644 index 000000000..dc8995446 --- /dev/null +++ b/circom/scripts/build_circuits.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -e + +OUTDIR=out + +[ -d "$OUTDIR" ] || mkdir "$OUTDIR" + +circom ./circuits/mux.circom --r1cs --wasm --sym -l ./node_modules -p bls12381 -o $OUTDIR + +cd $OUTDIR + +# Build a ptau for bls +snarkjs ptn bls12381 14 "pot_bls12381_14_0.ptau" +snarkjs powersoftau contribute "pot_bls12381_14_0.ptau" "pot_bls12381_14_1.ptau" --name="dev" -e="some random text" +snarkjs powersoftau prepare phase2 "pot_bls12381_14_1.ptau" "pot_bls12381_14_final.ptau" + +snarkjs groth16 setup mux.r1cs "pot_bls12381_14_final.ptau" mux.zkey +snarkjs zkey export verificationkey mux.zkey mux.vkey.json +snarkjs wtns calculate mux_js/mux.wasm ../input_mux.json "witness_mux.wtns" +snarkjs groth16 prove mux.zkey "witness_mux.wtns" "proof_mux.json" "public_mux.json" +snarkjs groth16 verify mux.vkey.json "public_mux.json" "proof_mux.json" \ No newline at end of file