@ -1,3 +1,9 @@ |
|||||
# sonobe docs |
# sonobe docs |
||||
[Introduction](README.md) |
[Introduction](README.md) |
||||
|
|
||||
|
- [Usage](usage/overview.md) |
||||
|
- [Frontend](usage/frontend.md) |
||||
|
- [Fold](usage/fold.md) |
||||
|
- [Decider prove](usage/decider-prove.md) |
||||
|
- [Solidity verifier](usage/solidity-verifier.md) |
||||
|
- [Modularity](usage/modularity.md) |
@ -0,0 +1,57 @@ |
|||||
|
# Decider prove |
||||
|
|
||||
|
Two options: |
||||
|
|
||||
|
- onchain (Ethereum's EVM) mode |
||||
|
- offchain mode |
||||
|
|
||||
|
Once we have been folding our circuit instances, we can generate the *"final proof"*, the Decider proof. |
||||
|
|
||||
|
|
||||
|
#### Onchain Decider |
||||
|
|
||||
|
 |
||||
|
|
||||
|
Generating the final proof (decider), to be able to verify it in Ethereum's EVM: |
||||
|
|
||||
|
```rust |
||||
|
type DECIDER = Decider< |
||||
|
Projective, |
||||
|
GVar, |
||||
|
Projective2, |
||||
|
GVar2, |
||||
|
CubicFCircuit<Fr>, |
||||
|
KZG<'static, Bn254>, |
||||
|
Pedersen<Projective2>, |
||||
|
Groth16<Bn254>, // here we define the Snark to use in the decider |
||||
|
NOVA, // here we define the FoldingScheme to use |
||||
|
>; |
||||
|
|
||||
|
// generate Groth16 setup |
||||
|
let circuit = DeciderEthCircuit::< |
||||
|
Projective, |
||||
|
GVar, |
||||
|
Projective2, |
||||
|
GVar2, |
||||
|
Pedersen<Projective>, |
||||
|
Pedersen<Projective2>, |
||||
|
>::from_nova::<CubicFCircuit<Fr>>(nova.clone()); |
||||
|
let mut rng = rand::rngs::OsRng; |
||||
|
|
||||
|
let start = Instant::now(); |
||||
|
let (pk, vk) = |
||||
|
Groth16::<Bn254>::circuit_specific_setup(circuit.clone(), &mut rng).unwrap(); |
||||
|
println!("Groth16 setup, {:?}", start.elapsed()); |
||||
|
|
||||
|
// decider proof generation |
||||
|
let decider_pp = (poseidon_config.clone(), g16_pk, kzg_pk); |
||||
|
let proof = DECIDER::prove(decider_pp, rng, nova.clone()).unwrap(); |
||||
|
|
||||
|
// decider proof verification |
||||
|
let decider_vp = (poseidon_config, g16_vk, kzg_vk); |
||||
|
let verified = DECIDER::verify(decider_vp, nova.i, nova.z_0, nova.z_i, &nova.U_i, &nova.u_i, proof).unwrap(); |
||||
|
assert!(verified); |
||||
|
``` |
||||
|
|
||||
|
As mentioned above, complete examples can be found at [sonobe/folding-schemes/examples](https://github.com/privacy-scaling-explorations/sonobe/tree/main/folding-schemes/examples) |
||||
|
|
@ -0,0 +1,50 @@ |
|||||
|
# Fold |
||||
|
|
||||
|
We plug our `FCircuit` 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<Fr>, |
||||
|
KZG<'static, Bn254>, |
||||
|
Pedersen<Projective2>, |
||||
|
>; |
||||
|
|
||||
|
let num_steps = 10; |
||||
|
let initial_state = vec![Fr::from(1_u32)]; |
||||
|
|
||||
|
let F_circuit = Sha256FCircuit::<Fr>::new(()); |
||||
|
|
||||
|
println!("Prepare Nova ProverParams & VerifierParams"); |
||||
|
let (prover_params, verifier_params) = nova_setup::<Sha256FCircuit<Fr>>(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, incoming_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, |
||||
|
incoming_instance, |
||||
|
cyclefold_instance, |
||||
|
) |
||||
|
.unwrap(); |
||||
|
``` |
@ -0,0 +1,43 @@ |
|||||
|
# Frontend |
||||
|
|
||||
|
The frontend interface allows to define the circuit to be folded. The available frontends are arkworks are Circom. |
||||
|
|
||||
|
We just need to fulfill the [`FCircuit` trait](https://github.com/privacy-scaling-explorations/sonobe/blob/main/sonobe/src/frontend/mod.rs): |
||||
|
|
||||
|
```rust |
||||
|
/// FCircuit defines the trait of the circuit of the F function, which is the one being folded (ie. |
||||
|
/// 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. |
||||
|
pub trait FCircuit<F: PrimeField>: Clone + Debug { |
||||
|
type Params: Debug; |
||||
|
|
||||
|
/// returns a new FCircuit instance |
||||
|
fn new(params: Self::Params) -> Self; |
||||
|
|
||||
|
/// returns the number of elements in the state of the FCircuit, which corresponds to the |
||||
|
/// FCircuit inputs. |
||||
|
fn state_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<F>, |
||||
|
) -> Result<Vec<F>, 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) |
||||
|
// can hold a state if needed to store data to generate the constraints. |
||||
|
&self, |
||||
|
cs: ConstraintSystemRef<F>, |
||||
|
i: usize, |
||||
|
z_i: Vec<FpVar<F>>, |
||||
|
) -> Result<Vec<FpVar<F>>, SynthesisError>; |
||||
|
} |
||||
|
``` |
||||
|
|
@ -0,0 +1,5 @@ |
|||||
|
# Modularity |
||||
|
## 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 [...] |
@ -0,0 +1,20 @@ |
|||||
|
# Usage |
||||
|
|
||||
|
## Folding schemes overview |
||||
|
(wip) |
||||
|
<!-- [introductory text here (TODO)] --> |
||||
|
|
||||
|
<img src="../imgs/folding-main-idea-diagram.png" style="width:70%;" /> |
||||
|
|
||||
|
[...] [this presentation](https://youtu.be/IzLTpKWt-yg?t=6367), where [Carlos Pérez](https://twitter.com/CPerezz19) overviews the features of folding schemes and what can be build with them. |
||||
|
|
||||
|
|
||||
|
## Sonobe overview |
||||
|
<!-- TODO explain the idea of sonobe, being a modular library to use different folding schemes --> |
||||
|
Suppose that the user inputs a circuit that follows the IVC structure, chooses which Folding Scheme to use (eg. Nova), and which Decider (eg. Spartan over Pasta curve). |
||||
|
|
||||
|
Later the user can for example change with few code changes the Folding Scheme being used (eg. switch to ProtoGalaxy) and also the Decider (eg. Groth16 over bn254), so the final proof can be verified in an Ethereum smart contract. |
||||
|
|
||||
|
 |
||||
|
|
||||
|
Complete examples can be found at [sonobe/folding-schemes/examples](https://github.com/privacy-scaling-explorations/sonobe/tree/main/folding-schemes/examples) |
@ -0,0 +1,8 @@ |
|||||
|
# Solidity verifier |
||||
|
|
||||
|
Having used the `DeciderEth` (see [Onchain Decider](#Onchain-Decider) section), we can now verify it in Ethereum's EVM. |
||||
|
|
||||
|
First we need to generate the Solidity contracts that verify the Decider proofs. Use the [solidity-verifiers-cli](cli) tool |
||||
|
``` |
||||
|
> solidity-verifier-cli -p nova-cyclefold -d ./folding-verifier-solidity/assets/G16_test_vk_data |
||||
|
``` |