circom-compat
circom-compat copied to clipboard
Verification fails when using generated zkey
Hello, we are facing an issue when we use our generated zkey, the verification process fails, but using a randomly generated proving key from the circom circuit the verification process works without any issues.
I made a simple repo to reproduce that issue here: https://github.com/shekohex/webb-ark-circom-issue
Please follow the instructions in the README file.
Any updates on this?
Use Circom version <= 2.0.6 and it will work.
I think you can actually do it with circom > 2.0.6, you just need to use create_random_proof_with_reduction
with CircomReduction
instead of create_random_proof
, which uses LibsnarkReduction
.
I used circom
2.1.5 to compile this multiplier circuit, then used snarkjs
0.6.10 to create a zkey.
Then, I tested it with this snippet using ark-circom ab7f9ec3a1202117981eb59854fa1aae2b1e4fee
use ark_circom::{CircomBuilder, CircomConfig, CircomReduction, read_zkey};
use ark_std::rand::thread_rng;
use color_eyre::Result;
use ark_bn254::Bn254;
use ark_groth16::{
create_random_proof_with_reduction, prepare_verifying_key, verify_proof,
};
#[test]
#[cfg(feature = "circom-2")]
fn circom2_1_5_test() -> Result<()> {
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem};
let cfg = CircomConfig::<Bn254>::new(
"./test-vectors/multiplier_circom_2.1.5.wasm",
"./test-vectors/multiplier_circom_2.1.5.r1cs",
)?;
let mut builder = CircomBuilder::new(cfg);
builder.push_input("in1", 2);
builder.push_input("in2", 2);
let mut rng = thread_rng();
let mut key_file = std::fs::File::open("./test-vectors/multiplier.zkey")?;
let (params, _) = read_zkey(&mut key_file)?;
let circom = builder.build()?;
let cs = ConstraintSystem::<ark_bn254::Fr>::new_ref();
circom.clone().generate_constraints(cs.clone()).unwrap();
let is_satisfied = cs.is_satisfied().unwrap();
assert!(is_satisfied);
let inputs = circom.get_public_inputs().unwrap();
let proof = create_random_proof_with_reduction::<Bn254, _, _, CircomReduction>(circom, ¶ms, &mut rng)?;
let pvk = prepare_verifying_key(¶ms.vk);
let verified = verify_proof(&pvk, &proof, &inputs)?;
assert!(verified);
Ok(())
}
Just a heads-up, the solution above works although the code is a bit different. Do what is told above, you can easily fill in the code changes (some functions now belong to Groth16, rather than being imported as a function) but the main trick is:
// using CircomReduction is important
type GrothBn254 = Groth16<Bn254, CircomReduction>;