From 3ec4ba1bef0571e92bd7687824e8a44606c36597 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Wed, 31 Jan 2024 12:12:26 +0100 Subject: [PATCH] readme: add example of FCircuit & folding --- README.md | 92 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 3308176f..0690d41a 100644 --- a/README.md +++ b/README.md @@ -30,15 +30,91 @@ Later the user can for example change with few code changes the Folding Scheme b ![](https://hackmd.io/_uploads/H1r7z9I32.png) *note: this diagram will be improved and done with some non-handwritten tool.* -### Folding the circuit +A complete example can be found at https://github.com/privacy-scaling-explorations/folding-schemes/blob/main/examples/fold_sha256.rs + +### Define the circuit to be folded First let's define our circuit to be folded: +```rust +/// This is the circuit that we want to fold, it implements the FCircuit trait +#[derive(Clone, Copy, Debug)] +pub struct Sha256FCircuit { + _f: PhantomData, +} +impl FCircuit for Sha256FCircuit { + type Params = (); + fn new(_params: Self::Params) -> Self { + Self { _f: PhantomData } + } + fn step_native(self, z_i: Vec) -> Result, Error> { + let out_bytes = Sha256::evaluate(&(), z_i[0].into_bigint().to_bytes_le()).unwrap(); + let out: Vec = out_bytes.to_field_elements().unwrap(); + Ok(vec![out[0]]) + } + fn generate_step_constraints( + self, + _cs: ConstraintSystemRef, + z_i: Vec>, + ) -> Result>, SynthesisError> { + let unit_var = UnitVar::default(); + let out_bytes = Sha256Gadget::evaluate(&unit_var, &z_i[0].to_bytes()?)?; + let out = out_bytes.0.to_constraint_field()?; + Ok(vec![out[0].clone()]) + } +} +``` + +We can also define the circuit in Circom: ```circom // ``` +### Folding the circuit Now we plug it into the library: ```rust -// +// The idea here is that eventually we could replace the next line chunk that defines the +// `type NOVA = Nova<...>` by using another folding scheme that fulfills the `FoldingScheme` +// trait, and the rest of our code would be working without needing to be updated. +type NOVA = Nova< + Projective, + GVar, + Projective2, + GVar2, + Sha256FCircuit, + Pedersen, + Pedersen, +>; + +let num_steps = 10; +let initial_state = vec![Fr::from(1_u32)]; + +let F_circuit = Sha256FCircuit::::new(()); + +println!("Prepare Nova ProverParams & VerifierParams"); +let (prover_params, verifier_params) = nova_setup::>(F_circuit); + +println!("Initialize FoldingScheme"); +let mut folding_scheme = NOVA::init(&prover_params, F_circuit, initial_state.clone()).unwrap(); + +// compute a step of the IVC +for i in 0..num_steps { + let start = Instant::now(); + folding_scheme.prove_step().unwrap(); + println!("Nova::prove_step {}: {:?}", i, start.elapsed()); +} + +let (running_instance, incomming_instance, cyclefold_instance) = folding_scheme.instances(); + +println!("Run the Nova's IVC verifier"); +NOVA::verify( + verifier_params, + initial_state, + folding_scheme.state(), // latest state + Fr::from(num_steps as u32), + running_instance, + incomming_instance, + cyclefold_instance, +) +.unwrap(); ``` ### Final proof (decider proof) @@ -56,18 +132,6 @@ Additionally, let's suppose that for the final proof (decider), instead of using It just requires few line changes on our previous code [...] -## Development -Structure of the code: - -[...] - -In each of the implementations of the folding dir, there are mainly 3 blocks plus 'other': -- circuits -- folding/nifs/nimfs -- ivc/lib -- other - - ## License https://github.com/privacy-scaling-explorations/folding-schemes/blob/main/LICENSE