diff --git a/src/README.md b/src/README.md
index 3a8afae..7f72917 100644
--- a/src/README.md
+++ b/src/README.md
@@ -22,14 +22,16 @@ The library uses [arkworks](https://github.com/arkworks-rs), and implements the
- [Nova: Recursive Zero-Knowledge Arguments from Folding Schemes](https://eprint.iacr.org/2021/370.pdf), Abhiram Kothapalli, Srinath Setty, Ioanna Tzialla. 2021
- [CycleFold: Folding-scheme-based recursive arguments over a cycle of elliptic curves](https://eprint.iacr.org/2023/1192.pdf), Abhiram Kothapalli, Srinath Setty. 2023
-
-Work in progress:
-
- [HyperNova: Recursive arguments for customizable constraint systems](https://eprint.iacr.org/2023/573.pdf), Abhiram Kothapalli, Srinath Setty. 2023
- [ProtoGalaxy: Efficient ProtoStar-style folding of multiple instances](https://eprint.iacr.org/2023/1106.pdf), Liam Eagen, Ariel Gabizon. 2023
-### Available frontends
-Available frontends to define the folded circuit:
-- [arkworks](https://github.com/arkworks-rs), arkworks contributors
-- [Circom](https://github.com/iden3/circom), iden3, 0Kims Association. Experimental frontend using [arkworks/circom-compat](https://github.com/arkworks-rs/circom-compat).
+### Frontends
+
+Frontends allow to define the circuit to be folded (ie. `FCircuit`).
+The recommended frontend is directly implementing the [`FCircuit` trait](https://github.com/privacy-scaling-explorations/sonobe/blob/main/folding-schemes/src/frontend/mod.rs#L16) with the Arkworks constraint system.
+
+Alternatively, experimental frontends for [Circom](https://github.com/iden3/circom), [Noir](https://github.com/noir-lang/noir) and [Noname](https://github.com/zksecurity/noname) can be found at the [sonobe/experimental-frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/experimental-frontends) directory, which have some computational (and time) overhead.
+
+More details about the frontend interface and the experimental frontends can be found at the [sonobe-docs/frontend](https://privacy-scaling-explorations.github.io/sonobe-docs/usage/frontend.html) page.
+
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 654b1bc..08687e3 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -6,12 +6,9 @@
- [Usage](usage/overview.md)
- [Frontend](usage/frontend.md)
- [Arkworks](usage/frontend-arkworks.md)
- - [Circom](usage/frontend-circom.md)
- - [Noir](usage/frontend-noir.md)
- - [Noname](usage/frontend-noname.md)
+ - [Experimental frontends](usage/experimental-frontends.md)
- [Fold](usage/fold.md)
- - [Decider prove](usage/decider-prove.md)
- - [Decider verify](usage/decider-verify.md)
+ - [Decider](usage/decider.md)
- [Solidity verifier](usage/solidity-verifier.md)
- [Nova's zero-knowledge layer](usage/nova-zk.md)
- [WASM - browser usage](usage/wasm.md)
diff --git a/src/examples_projects.md b/src/examples_projects.md
index 8028254..457c70c 100644
--- a/src/examples_projects.md
+++ b/src/examples_projects.md
@@ -4,9 +4,10 @@
- [sonobe-btc](https://github.com/dmpierre/sonobe-btc): implementation of an on-chain Bitcoin light client leveraging Sonobe: uses nova to verify bitcoin's proof of work over 100k blocks and groth16 to land the zkSNARK IVC proof on chain.
- [hash-chain-sonobe](https://github.com/arnaucube/hash-chain-sonobe): example using Sonobe & Circom circuits, proving chains of Sha256 and Keccak256 hashes.
+- [ethdos-fold](https://github.com/arnaucube/ethdos-fold): implementation of [ETHdos](https://ethdos.xyz/blog) using folding schemes.
-## Papers
+## Related papers
- [Mova: Nova folding without committing to error terms](https://eprint.iacr.org/2024/1220): a folding scheme for R1CS instances that does not require committing to error or cross terms. It is implemented on top of Sonobe code base, and used for benchmarks, see their repo [here](https://github.com/NethermindEth/sonobe/tree/paper).
- [Eva: Efficient IVC-Based Authentication of Lossy-Encoded Videos](https://eprint.iacr.org/2024/1436): cryptographic protocol for authenticating lossy-encoded videos. Is implemented on top of Sonobe code base.
diff --git a/src/experimental-frontends.md b/src/experimental-frontends.md
new file mode 100644
index 0000000..bddcb43
--- /dev/null
+++ b/src/experimental-frontends.md
@@ -0,0 +1 @@
+# Experimental frontends
diff --git a/src/folding-and-sonobe.md b/src/folding-and-sonobe.md
index 3f651ce..52cb19b 100644
--- a/src/folding-and-sonobe.md
+++ b/src/folding-and-sonobe.md
@@ -15,10 +15,11 @@ In other words, it allows to prove efficiently that $z_n = F(...~F(F(F(F(z_0, w_
-The next 3 videos provide a good overview of folding schemes:
+The next 3 videos provide an overview of the main ideas in folding schemes (sorted from more high level to deepest into the concepts):
- In [this presentation](https://www.youtube.com/watch?v=Jj19k2AXH2k) (5 min) Abhiram Kothapalli explains the main idea of Nova folding scheme.
- In [this presentation](https://youtu.be/IzLTpKWt-yg?t=6367) (20 min) Carlos Pérez overviews the features of folding schemes and what can be built with them.
-- In [this presentation](https://www.youtube.com/watch?v=SwonTtOQzAk) (1h) Justin Drake explains what a folding scheme is and Nova-related concepts.
+- In [this presentation](https://www.youtube.com/watch?v=z3FH9I8klDk) (30min) arnaucube overivews the main building blocks on folding schemes and showcases the usage of Sonobe.
+- In [this presentation](https://www.youtube.com/watch?v=4alOna5X3ro) (1h) Albert Garreta dives into the math behind folding schemes.
## Sonobe overview
diff --git a/src/usage/decider-verify.md b/src/usage/decider-verify.md
deleted file mode 100644
index 34d9a53..0000000
--- a/src/usage/decider-verify.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Decider verify
-We can now verify the Decider proof
-
-```rust
-// this is the same that we defined for the prover
-type DECIDER = Decider<
- Projective,
- GVar,
- Projective2,
- GVar2,
- CubicFCircuit,
- KZG<'static, Bn254>,
- Pedersen,
- Groth16,
- NOVA,
->;
-
-let verified = DECIDER::verify(
- decider_vp, nova.i, nova.z_0, nova.z_i, &nova.U_i, &nova.u_i, proof,
-)
-.unwrap();
-assert!(verified);
-```
-
-In the Ethereum Decider case, we can generate a Solidity smart contract that verifies the proofs onchain. More details in the [next section](solidity-verifier.md).
diff --git a/src/usage/decider-prove.md b/src/usage/decider.md
similarity index 61%
rename from src/usage/decider-prove.md
rename to src/usage/decider.md
index 68728b0..23b9d63 100644
--- a/src/usage/decider-prove.md
+++ b/src/usage/decider.md
@@ -1,4 +1,6 @@
-# Decider prove
+# Decider
+
+## Decider prove
Two options:
@@ -17,14 +19,12 @@ Generating the final proof (decider), to be able to verify it in Ethereum's EVM:
```rust
type DECIDER = Decider<
Projective,
- GVar,
Projective2,
- GVar2,
CubicFCircuit,
KZG<'static, Bn254>,
Pedersen,
Groth16, // here we define the Snark to use in the decider
- NOVA, // here we define the FoldingScheme to use
+ NOVA, // here we define the FoldingScheme to use
>;
let mut rng = rand::rngs::OsRng;
@@ -38,3 +38,27 @@ let proof = DECIDER::prove(rng, decider_pp, nova.clone()).unwrap();
```
As in the previous sections, you can find a full examples with all the code at [sonobe/examples](https://github.com/privacy-scaling-explorations/sonobe/tree/main/examples).
+
+## Decider verify
+We can now verify the Decider proof
+
+```rust
+// this is the same that we defined for the prover
+type DECIDER = Decider<
+ Projective,
+ Projective2,
+ CubicFCircuit,
+ KZG<'static, Bn254>,
+ Pedersen,
+ Groth16,
+ NOVA,
+>;
+
+let verified = DECIDER::verify(
+ decider_vp, nova.i, nova.z_0, nova.z_i, &nova.U_i, &nova.u_i, proof,
+)
+.unwrap();
+assert!(verified);
+```
+
+In the Ethereum Decider case, we can generate a Solidity smart contract that verifies the proofs onchain. More details in the [next section](solidity-verifier.md).
diff --git a/src/usage/frontend-circom.md b/src/usage/experimental-frontends.md
similarity index 61%
rename from src/usage/frontend-circom.md
rename to src/usage/experimental-frontends.md
index d0f6dc2..5bf99c6 100644
--- a/src/usage/frontend-circom.md
+++ b/src/usage/experimental-frontends.md
@@ -1,4 +1,20 @@
-# Circom frontend
+# Experimental frontends
+> Warning: the following frontends are experimental and some computational and time overhead is expected when using them compared to directly using the [arkworks frontend](frontend-arkworks.md).
+
+
+This section overviews how to use the various experimental frontends:
+- [implementing new frontends](#implementing-new-frontends)
+- [Circom frontend](#circom-frontend)
+- [Noname frontend](#noname-frontend)
+- [Noir frontend](#noir-frontend)
+
+
+## Implementing new frontends
+
+Support for new frontends can be added (even from outside this repo) by implementing the [`FCircuit` trait](https://github.com/privacy-scaling-explorations/sonobe/blob/main/folding-schemes/src/frontend/mod.rs).
+
+
+## Circom frontend
> **Note**: Circom frontend will be significantly slower than the Arkworks frontend. We explain below how to implement a custom `step_native` function with your circom circuits to speed things up!
Experimental frontend using [arkworks/circom-compat](https://github.com/arkworks-rs/circom-compat).
@@ -107,3 +123,21 @@ for (i, external_inputs_at_step) in external_inputs.iter().enumerate() {
```
You can find a full example using Nova to fold a Circom circuit at [sonobe/examples/circom_full_flow.rs](https://github.com/privacy-scaling-explorations/sonobe/blob/main/examples/circom_full_flow.rs).
+
+
+## Noname frontend
+
+Experimental [Noname](https://github.com/zksecurity/noname/). Under the hood, we [bridge](https://github.com/dmpierre/ark-noname/tree/feat/sonobe-integration) compiled Noname circuits to arkworks R1CS. Our Noname integration does not support Noname's standard library for now.
+
+Using Noname with sonobe is similar to using any other frontend. Sonobe expects that the length of your public and private (external) inputs match what the Noname circuit expects. Note that sonobe does not expect your public inputs to follow some specific naming convention when using Noname: it will assume that whatever public input variable you have is the IVC state.
+
+This [example](https://github.com/privacy-scaling-explorations/sonobe/blob/main/examples/noname_full_flow.rs) shows how to fold a simple Noname circuit having both public and external, private inputs.
+
+
+## Noir frontend
+
+Experimental [Noir](https://noir-lang.org/) frontend. Under the hood, we [bridge](https://github.com/dmpierre/arkworks_backend) compiled Noir circuits to arkworks R1CS. Beware that sonobe assumes that the compiled Noir circuit that is being folded does not use any other opcode than an arithmetic gate: you can not fold circuits calling [oracles](https://noir-lang.org/docs/noir/concepts/oracles) or using [unconstrained](https://noir-lang.org/docs/noir/concepts/unconstrained/) functions. You should be able to use Noir's standard library though.
+
+Using Noir with sonobe is similar to using any other frontend. Sonobe expects that the length of your public and private (external) inputs match what the Noir circuit expects. Note that sonobe does not expect your public inputs to follow some specific naming convention when using Noir: it will assume that whatever public input variable you have is the IVC state.
+
+This [example](https://github.com/privacy-scaling-explorations/sonobe/blob/main/examples/noir_full_flow.rs) shows how to fold a poseidon circuit from the Noir standard library.
diff --git a/src/usage/fold.md b/src/usage/fold.md
index 458171c..622e58f 100644
--- a/src/usage/fold.md
+++ b/src/usage/fold.md
@@ -6,16 +6,7 @@ We plug our `FCircuit` into the library:
// The idea here is that 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 F = Nova<
- Projective,
- GVar,
- Projective2,
- GVar2,
- Sha256FCircuit,
- KZG<'static, Bn254>,
- Pedersen,
- false,
->;
+type FS = Nova, Pedersen, Pedersen, false>;
let num_steps = 10;
let initial_state = vec![Fr::from(1_u32)];
@@ -27,11 +18,11 @@ let mut rng = rand::rngs::OsRng;
println!("Prepare Nova ProverParams & VerifierParams");
let nova_preprocess_params = PreprocessorParam::new(poseidon_config, F_circuit);
-let nova_params = FS::preprocess(&mut rng, &nova_preprocess_params).unwrap();
+let nova_params = FS::preprocess(&mut rng, &nova_preprocess_params)?;
println!("Initialize FoldingScheme");
-let mut folding_scheme = FS::init(&nova_params, F_circuit, initial_state.clone()).unwrap();
+let mut folding_scheme = FS::init(&nova_params, F_circuit, initial_state.clone())?;
// compute a step of the IVC
@@ -42,43 +33,37 @@ for i in 0..num_steps {
// - 3rd parameter: is for schemes that support folding more than 2
// instances at each fold, such as HyperNova. Since we're using Nova, we just
// set it to 'None'
- folding_scheme.prove_step(rng, vec![], None).unwrap();
+ folding_scheme.prove_step(rng, (), None)?;
println!("Nova::prove_step {}: {:?}", i, start.elapsed());
}
-let (running_instance, incoming_instance, cyclefold_instance) = folding_scheme.instances();
+let ivc_proof: FS::IVCProof = folding_scheme.ivc_proof();
println!("Run the Nova's IVC verifier");
-FS::verify(
- nova_params.1,
- initial_state,
- folding_scheme.state(), // latest state
- Fr::from(num_steps as u32),
- running_instance,
- incoming_instance,
- cyclefold_instance,
-)
-.unwrap();
+FS::verify(nova_params.1, ivc_proof)?;
```
+Observe that we define the folding scheme to be used with the following line:
+```rust
+type FS = Nova, Pedersen, false>;
+```
+
+(where `FC` is the `FCircuit` that we want to fold).
+
Now imagine that we want to switch the folding scheme being used. Is as simple as replacing `FS` by:
```rust
-type FS = HyperNova<
- Projective,
- GVar,
- Projective2,
- GVar2,
- CubicFCircuit,
- KZG<'static, Bn254>,
- Pedersen,
- 1, 1, false,
->;
+type FS = HyperNova< G1, G2, FC, Pedersen, Pedersen, 1, 1, false>;
```
and then adapting the `folding_scheme.prove_step(...)` call accordingly.
+Similarly for using ProtoGalaxy folding schemes:
+```rust
+type FS = ProtoGalaxy, Pedersen>;
+```
+
diff --git a/src/usage/frontend-arkworks.md b/src/usage/frontend-arkworks.md
index 1c82527..d2a6779 100644
--- a/src/usage/frontend-arkworks.md
+++ b/src/usage/frontend-arkworks.md
@@ -1,6 +1,6 @@
# Arkworks frontend
-Let's walk through different simple examples implementing the `FCircuit` trait. By the end of this section, you will hopefully be familiar with how to integrate an `arkworks` circuit into sonobe.
+Let's walk through different simple examples implementing the `FCircuit` trait. By the end of this section, you will hopefully be familiar with how to integrate an `arkworks` circuit into Sonobe.
You can find most of the following examples with the rest of code to run them at the [`examples`](https://github.com/privacy-scaling-explorations/sonobe/tree/main/examples) directory of the Sonobe repo.
@@ -16,29 +16,21 @@ pub struct CubicFCircuit {
}
impl FCircuit for CubicFCircuit {
type Params = ();
+ type ExternalInputs = ();
+ type ExternalInputsVar = ();
+
fn new(_params: Self::Params) -> Result {
Ok(Self { _f: PhantomData })
}
fn state_len(&self) -> usize {
1
}
- fn external_inputs_len(&self) -> usize {
- 0
- }
- fn step_native(
- &self,
- _i: usize,
- z_i: Vec,
- _external_inputs: Vec,
- ) -> Result, Error> {
- Ok(vec![z_i[0] * z_i[0] * z_i[0] + z_i[0] + F::from(5_u32)])
- }
fn generate_step_constraints(
&self,
cs: ConstraintSystemRef,
_i: usize,
z_i: Vec>,
- _external_inputs: Vec>,
+ _external_inputs: Self::ExternalInputsVar,
) -> Result>, SynthesisError> {
let five = FpVar::::new_constant(cs.clone(), F::from(5u32))?;
let z_i = z_i[0].clone();
@@ -68,41 +60,22 @@ pub struct MultiInputsFCircuit {
}
impl FCircuit for MultiInputsFCircuit {
type Params = ();
+ type ExternalInputs = ();
+ type ExternalInputsVar = ();
fn new(_params: Self::Params) -> Result {
Ok(Self { _f: PhantomData })
}
fn state_len(&self) -> usize {
- 5 // since the circuit has 5 inputs
- }
- fn external_inputs_len(&self) -> usize {
- 0
+ 5
}
-
- /// computes the next state values in place, assigning z_{i+1} into z_i, and computing the new
- /// z_{i+1}
- fn step_native(
- &self,
- _i: usize,
- z_i: Vec,
- _external_inputs: Vec,
- ) -> Result, Error> {
- let a = z_i[0] + F::from(4_u32);
- let b = z_i[1] + F::from(40_u32);
- let c = z_i[2] * F::from(4_u32);
- let d = z_i[3] * F::from(40_u32);
- let e = z_i[4] + F::from(100_u32);
-
- Ok(vec![a, b, c, d, e])
- }
-
/// generates the constraints for the step of F for the given z_i
fn generate_step_constraints(
&self,
cs: ConstraintSystemRef,
_i: usize,
z_i: Vec>,
- _external_inputs: Vec>,
+ _external_inputs: Self::ExternalInputsVar,
) -> Result>, SynthesisError> {
let four = FpVar::::new_constant(cs.clone(), F::from(4u32))?;
let forty = FpVar::::new_constant(cs.clone(), F::from(40u32))?;
@@ -173,6 +146,8 @@ where
F: Absorb,
{
type Params = PoseidonConfig;
+ type ExternalInputs = [F; 1];
+ type ExternalInputsVar = [FpVar; 1];
fn new(params: Self::Params) -> Result {
Ok(Self {
@@ -183,23 +158,6 @@ where
fn state_len(&self) -> usize {
1
}
- fn external_inputs_len(&self) -> usize {
- 1
- }
-
- /// computes the next state value for the step of F for the given z_i and external_inputs
- /// z_{i+1}
- fn step_native(
- &self,
- _i: usize,
- z_i: Vec,
- external_inputs: Vec,
- ) -> Result, Error> {
- let hash_input: [F; 2] = [z_i[0], external_inputs[0]];
- let h = CRH::::evaluate(&self.poseidon_config, hash_input).unwrap();
- Ok(vec![h])
- }
-
/// generates the constraints and returns the next state value for the step of F for the given
/// z_i and external_inputs
fn generate_step_constraints(
@@ -207,7 +165,7 @@ where
cs: ConstraintSystemRef,
_i: usize,
z_i: Vec>,
- external_inputs: Vec>,
+ external_inputs: Self::ExternalInputsVar,
) -> Result>, SynthesisError> {
let crh_params =
CRHParametersVar::::new_constant(cs.clone(), self.poseidon_config.clone())?;
diff --git a/src/usage/frontend-noir.md b/src/usage/frontend-noir.md
deleted file mode 100644
index b27ed10..0000000
--- a/src/usage/frontend-noir.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Noir frontend
-
-Experimental frontend using [arkworks_backend](https://github.com/dmpierre/arkworks_backend).
-
-If you write your R1CS circuits using [Noir](https://noir-lang.org/), you can also use [sonobe](https://github.com/privacy-scaling-explorations/sonobe/) to fold your circuits. Under the hood, we bridge compiled Noir circuits to arkworks R1CS. Beware that sonobe assumes that the compiled Noir circuit that is being folded does not use any other opcode than an arithmetic gate: you can not fold circuits calling [oracles](https://noir-lang.org/docs/noir/concepts/oracles) or using [unconstrained](https://noir-lang.org/docs/noir/concepts/unconstrained/) functions. You should be able to use Noir's standard library though.
-
-Using Noir with sonobe is similar to using any other frontend. Sonobe expects that the length of your public and private (external) inputs match what the Noir circuit expects. Note that sonobe does not expect your public inputs to follow some specific naming convention when using Noir: it will assume that whatever public input variable you have is the IVC state.
-
-This [example](https://github.com/privacy-scaling-explorations/sonobe/blob/main/examples/noir_full_flow.rs) shows how to fold a poseidon circuit from the Noir standard library.
-
diff --git a/src/usage/frontend-noname.md b/src/usage/frontend-noname.md
deleted file mode 100644
index bc0aa1f..0000000
--- a/src/usage/frontend-noname.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Noname frontend
-
-Experimental frontend using [ark-noname](https://github.com/dmpierre/ark-noname/tree/feat/sonobe-integration).
-
-If you write your R1CS circuits using [Noname](), you can also use [sonobe](https://github.com/privacy-scaling-explorations/sonobe/) to fold your circuits. Under the hood, we bridge compiled Noname circuits to arkworks R1CS. Our Noname integration does not support Noname's standard library for now.
-
-Using Noname with sonobe is similar to using any other frontend. Sonobe expects that the length of your public and private (external) inputs match what the Noname circuit expects. Note that sonobe does not expect your public inputs to follow some specific naming convention when using Noname: it will assume that whatever public input variable you have is the IVC state.
-
-This [example](https://github.com/privacy-scaling-explorations/sonobe/blob/main/examples/noname_full_flow.rs) shows how to fold a simple Noname circuit having both public and external, private inputs.
-
diff --git a/src/usage/frontend.md b/src/usage/frontend.md
index bb4347e..f704ca4 100644
--- a/src/usage/frontend.md
+++ b/src/usage/frontend.md
@@ -3,7 +3,7 @@
The frontend interface allows to define the circuit to be folded.
The recommended frontend is to directly use [arkworks](https://github.com/arkworks-rs) to define the FCircuit, just following the [`FCircuit` trait](https://github.com/privacy-scaling-explorations/sonobe/blob/main/folding-schemes/src/frontend/mod.rs).
-Alternatively, experimental frontends for [Circom](https://github.com/iden3/circom), [Noir](https://noir-lang.org/), and [Noname](https://github.com/zksecurity/noname) can be found at [sonobe/frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/frontends), which have some computational (and time) overhead.
+Alternatively, experimental frontends for [Circom](https://github.com/iden3/circom), [Noir](https://noir-lang.org/), and [Noname](https://github.com/zksecurity/noname) can be found at [sonobe/experimental-frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/experimental-frontends), which have some computational (and time) overhead.
Defining a circuit to be folded is as simple as fulfilling the `FCircuit` trait interface. Henceforth, integrating a new zk circuits language into Sonobe, can be done by building a wrapper on top of it that satisfies the `FCircuit` trait.
@@ -17,8 +17,14 @@ To be folded with sonobe, a circuit needs to implement the [`FCircuit` trait](ht
/// inside the agmented F' function).
/// The parameter z_i denotes the current state, and z_{i+1} denotes the next state after applying
/// the step.
+/// Note that the external inputs for the specific circuit are defined at the implementation of
+/// both `FCircuit::ExternalInputs` and `FCircuit::ExternalInputsVar`, where the `Default` trait
+/// implementation. For example if the external inputs are just an array of field elements, their
+/// `Default` trait implementation must return an array of the expected size.
pub trait FCircuit: Clone + Debug {
type Params: Debug;
+ type ExternalInputs: Clone + Default + Debug;
+ type ExternalInputsVar: Clone + Default + Debug + AllocVar;
/// returns a new FCircuit instance
fn new(params: Self::Params) -> Result;
@@ -27,21 +33,6 @@ pub trait FCircuit: Clone + Debug {
/// FCircuit inputs.
fn state_len(&self) -> usize;
- /// returns the number of elements in the external inputs used by the FCircuit. External inputs
- /// are optional, and in case no external inputs are used, this method should return 0.
- fn external_inputs_len(&self) -> usize;
-
- /// computes the next state values in place, assigning z_{i+1} into z_i, and computing the new
- /// z_{i+1}
- fn step_native(
- // this method uses self, so that each FCircuit implementation (and different frontends)
- // can hold a state if needed to store data to compute the next state.
- &self,
- i: usize,
- z_i: Vec,
- external_inputs: Vec, // inputs that are not part of the state
- ) -> Result, Error>;
-
/// generates the constraints for the step of F for the given z_i
fn generate_step_constraints(
// this method uses self, so that each FCircuit implementation (and different frontends)
@@ -50,13 +41,13 @@ pub trait FCircuit: Clone + Debug {
cs: ConstraintSystemRef,
i: usize,
z_i: Vec>,
- external_inputs: Vec>, // inputs that are not part of the state
+ external_inputs: Self::ExternalInputsVar, // inputs that are not part of the state
) -> Result>, SynthesisError>;
}
```
-# Side note: adhoc frontend dependencies for the experimental frontends
-> Note: this affects only to the experimental frontends in the [sonobe/frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/frontends) directory.
+## Side note: adhoc frontend dependencies for the experimental frontends
+> Note: this affects only to the experimental frontends in the [sonobe/experimental-frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/experimental-frontends) directory.
There are many ad hoc dependencies for each of the frontends integrated with Sonobe. Here are a few reasons why this is the case.
diff --git a/src/usage/modularity.md b/src/usage/modularity.md
index 8a400a4..1ecdbf3 100644
--- a/src/usage/modularity.md
+++ b/src/usage/modularity.md
@@ -2,4 +2,21 @@
## Swapping curves and proving schemes
Thanks to the modularity of arkworks, we can swap between curves and proving systems.
Suppose that for the final proof (decider), instead of using Groth16 over the BN254 curve, we want to use Marlin+IPA over the Pasta curves, so we can enjoy of not needing a trusted setup.
-It just requires few line changes on our previous code [...]
+
+It just requires few line changes on our previous code, for example, imagine we're using the Nova folding scheme (where `FC` is the `FCircuit` that we want to fold):
+```rust
+type FS = Nova, Pedersen, false>;
+```
+
+to switch the folding scheme to use HyperNova, is as simple as updating the previous line to:
+
+```rust
+type FS = HyperNova< G1, G2, FC, Pedersen, Pedersen, 1, 1, false>;
+```
+
+similarly for using ProtoGalaxy folding scheme:
+```rust
+type FS = ProtoGalaxy, Pedersen>;
+```
+
+We can use any cycle of curves available in arkworks for the `G1` and `G2`, and the rest of the code can be kept the same.
diff --git a/src/usage/nova-zk.md b/src/usage/nova-zk.md
index 41283b0..d414f0a 100644
--- a/src/usage/nova-zk.md
+++ b/src/usage/nova-zk.md
@@ -10,11 +10,11 @@ Nova's zk-IVC proof generation is quite efficient, as it simply involves blindin
We identify 3 main interesting places to use the nova zk-layer: one before all the folding pipeline (Use-case-1), one at the end of the folding pipeline right before the final Decider SNARK proof (Use-case-2), and a third one for cases where compressed SNARK proofs are not needed, and just IVC proofs (bigger than SNARK proofs) suffice (Use-case-3):
-- Use-case-1: at the beginning of the folding pipeline, right when the user has their original instance prior to be folded into the running instance, the user can fold it with the random-satisfying-instance to then have a blinded instance that can be sent to a server that will fold it with the running instance.
+- **Use-case-1**: at the beginning of the folding pipeline, right when the user has their original instance prior to be folded into the running instance, the user can fold it with the random-satisfying-instance to then have a blinded instance that can be sent to a server that will fold it with the running instance.
- In this one, the user could externalize all the IVC folding and also the Decider final proof generation to a server.
-- Use-case-2: at the end of all the IVC folding steps (after n iterations of nova.prove_step), to 'blind' the IVC proof so then it can be sent to a server that will generate the final Decider SNARK proof.
+- **Use-case-2**: at the end of all the IVC folding steps (after n iterations of nova.prove_step), to 'blind' the IVC proof so then it can be sent to a server that will generate the final Decider SNARK proof.
- In this one, the user could externalize the Decider final proof generation to a server.
-- Use-case-3: the user does not care about the Decider (final compressed SNARK proof), and wants to generate a zk-proof of the last IVC state to an IVC verifier (without any SNARK proof involved). In this use-case, the zk is only added at the last IVCProof. Note that this proof will be much bigger and expensive to verify than a Decider SNARK proof.
+- **Use-case-3**: the user does not need the Decider (final compressed SNARK proof), and wants to generate a zk-proof of the last IVC state to an IVC verifier (without any SNARK proof involved, and without continuing folding after this last proof). In this use-case, the zk is only added at the last IVCProof. Note that this proof will be much bigger and expensive to verify than a Decider SNARK proof.
The current implementation available in Sonobe covers the Use-case-3.
Use-case-1 can be achieved directly by a simpler version of the zk IVC scheme skipping steps and implemented directly at the app level by folding the original instance with a randomized instance (steps 2,3,4 from section D.4 of the [HyperNova](https://eprint.iacr.org/2023/573.pdf)