From d05ceab56a1a3fa5664e8d696e0fab5907941b82 Mon Sep 17 00:00:00 2001 From: dmpierre Date: Thu, 6 Jun 2024 15:05:57 +0200 Subject: [PATCH] chore: add example of folding a circom circuit and explain how to use a custom `step_native` function --- src/usage/frontend-circom.md | 47 +++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/usage/frontend-circom.md b/src/usage/frontend-circom.md index 9a30f79..922a60c 100644 --- a/src/usage/frontend-circom.md +++ b/src/usage/frontend-circom.md @@ -38,5 +38,50 @@ template Example () { ivc_output[0] <== temp1 * ivc_input[0] + temp2 + external_inputs[1]; } -component main {public [ivc_input]} = Example(); +component main {public [ivc_input]} = CubicCircuit(); +``` + +Once your `circom` circuit is ready, you can instantiate it with Sonobe. To do this, you will need the `struct CircomFCircuit`. + +```rust +// we load our circom compiled R1CS, along with the witness wasm calculator +let r1cs_path = PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit.r1cs"); + let wasm_path = + PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); +let mut circom_fcircuit = CircomFCircuit::::new((r1cs_path, wasm_path, 1, 2)).unwrap(); // state_len:1, external_inputs_len:2 + +// to speed things up, you can define a custom step function to avoid defaulting to the snarkjs witness calculator +circom_fcircuit.set_custom_step_native(Rc::new(|_i, z_i, _external| { + let z = z_i[0]; + Ok(vec![z * z * z + z + Fr::from(5)]) + })); + +// we initialize the required folding schemes parameters, the folding scheme and the final decider that we want to use +let (fs_prover_params, kzg_vk, g16_pk, g16_vk) = + init_ivc_and_decider_params::>(f_circuit.clone()); + +pub type NOVA = Nova, KZG<'static, Bn254>, Pedersen>; +pub type DECIDERETH_FCircuit = DeciderEth< + G1, + GVar, + G2, + GVar2, + CircomFCircuit, + KZG<'static, Bn254>, + Pedersen, + Groth16, + NOVA, +>; + +// initialize the folding scheme engine, in our case we use Nova +let mut nova = NOVA::init(&fs_prover_params, f_circuit.clone(), z_0).unwrap(); + +// run n steps of the folding iteration +for (i, external_inputs_at_step) in external_inputs.iter().enumerate() { + let start = Instant::now(); + nova.prove_step(external_inputs_at_step.clone()).unwrap(); + println!("Nova::prove_step {}: {:?}", i, start.elapsed()); +} + ``` +You can find an example for using Nova over a circom circuit [here](https://github.com/privacy-scaling-explorations/sonobe/blob/main/examples/circom_full_flow.rs).