mirror of
https://github.com/arnaucube/sonobe.git
synced 2026-01-18 11:51:33 +01:00
Add solidity groth16, kzg10 and final decider verifiers in a dedicated workspace (#70)
* change: Refactor structure into workspace * chore: Add empty readme * change: Transform repo into workspace * add: Create folding-verifier-solidity crate * add: Include askama.toml for `sol` extension escaper * add: Jordi's old Groth16 verifier .sol template and adapt it * tmp: create simple template struct to test * Update FoldingSchemes trait, fit Nova+CycleFold - update lib.rs's `FoldingScheme` trait interface - fit Nova+CycleFold into the `FoldingScheme` trait - refactor `src/nova/*` * chore: add serialization assets for testing Now we include an `assets` folder with a serialized proof & vk for tests * Add `examples` dir, with Nova's `FoldingScheme` example * polishing * expose poseidon_test_config outside tests * change: Refactor structure into workspace * chore: Add empty readme * change: Transform repo into workspace * add: Create folding-verifier-solidity crate * add: Include askama.toml for `sol` extension escaper * add: Jordi's old Groth16 verifier .sol template and adapt it * tmp: create simple template struct to test * feat: templating kzg working * chore: add emv and revm * feat: start evm file * chore: add ark-poly-commit * chore: move `commitment` to `folding-schemes` * chore: update `.gitignore` to ignore generated contracts * chore: update template with bn254 lib on it (avoids import), update for loop to account for whitespaces * refactor: update template with no lib * feat: add evm deploy code, compile and create kzg verifier * chore: update `Cargo.toml` to have `folding-schemes` available with verifiers * feat: start kzg prove and verify with sol * chore: compute crs from kzg prover * feat: evm kzg verification passing * tmp * change: Swap order of G2 coordinates within the template * Update way to serialize proof with correct order * chore: update `Cargo.toml` * chore: add revm * chore: add `save_solidity` * refactor: verifiers in dedicated mod * refactor: have dedicated `utils` module * chore: expose modules * chore: update verifier for kzg * chore: rename templates * fix: look for binary using also name of contract * refactor: generate groth16 proof for sha256 pre-image, generate groth16 template with verifying key * chore: template renaming * fix: switch circuit for circuit that simply adds * feat: generates test data on the fly * feat: update to latest groth16 verifier * refactor: rename folder, update `.gitignore` * chore: update `Cargo.toml` * chore: update templates extension to indicate that they are templates * chore: rename templates, both files and structs * fix: template inheritance working * feat: template spdx and pragma statements * feat: decider verifier compiles, update test for kzg10 and groth16 templates * feat: parameterize which size of the crs should be stored on the contract * chore: add comment on how the groth16 and kzg10 proofs will be linked together * chore: cargo clippy run * chore: cargo clippy tests * chore: cargo fmt * refactor: remove unused lifetime parameter * chore: end merge * chore: move examples to `folding-schemes` workspace * get latest main changes * fix: temp fix clippy warnings, will remove lints once not used in tests only * fix: cargo clippy lint added on `code_size` * fix: update path to test circuit and add step for installing solc * chore: remove `save_solidity` steps * fix: the borrowed expression implements the required traits * chore: update `Cargo.toml` * chore: remove extra `[patch.crates-io]` * fix: update to patch at the workspace level and add comment explaining this * refactor: correct `staticcall` with valid input/output sizes and change return syntax for pairing * refactor: expose modules and remove `dead_code` calls * chore: update `README.md`, add additional comments on `kzg10` template and update `groth16` template comments * chore: be clearer on attributions on `kzg10` --------- Co-authored-by: CPerezz <c.perezbaro@gmail.com> Co-authored-by: arnaucube <root@arnaucube.com>
This commit is contained in:
171
folding-schemes/src/frontend/mod.rs
Normal file
171
folding-schemes/src/frontend/mod.rs
Normal file
@@ -0,0 +1,171 @@
|
||||
pub mod circom;
|
||||
|
||||
use crate::Error;
|
||||
use ark_ff::PrimeField;
|
||||
use ark_r1cs_std::fields::fp::FpVar;
|
||||
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
|
||||
use ark_std::fmt::Debug;
|
||||
|
||||
/// 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 + Copy + Debug {
|
||||
type Params: Debug;
|
||||
|
||||
/// returns a new FCircuit instance
|
||||
fn new(params: Self::Params) -> Self;
|
||||
|
||||
/// 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,
|
||||
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>,
|
||||
z_i: Vec<FpVar<F>>,
|
||||
) -> Result<Vec<FpVar<F>>, SynthesisError>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use ark_pallas::Fr;
|
||||
use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget};
|
||||
use ark_relations::r1cs::{
|
||||
ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError,
|
||||
};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// CubicFCircuit is a struct that implements the FCircuit trait, for the R1CS example circuit
|
||||
/// from https://www.vitalik.ca/general/2016/12/10/qap.html, which checks `x^3 + x + 5 = y`. It
|
||||
/// has 2 public inputs which are used as the state. `z_i` is used as `x`, and `z_{i+1}` is
|
||||
/// used as `y`, and at the next step, `z_{i+1}` will be assigned to `z_i`, and a new `z+{i+1}`
|
||||
/// will be computted.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct CubicFCircuit<F: PrimeField> {
|
||||
_f: PhantomData<F>,
|
||||
}
|
||||
impl<F: PrimeField> FCircuit<F> for CubicFCircuit<F> {
|
||||
type Params = ();
|
||||
fn new(_params: Self::Params) -> Self {
|
||||
Self { _f: PhantomData }
|
||||
}
|
||||
fn step_native(self, z_i: Vec<F>) -> Result<Vec<F>, 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<F>,
|
||||
z_i: Vec<FpVar<F>>,
|
||||
) -> Result<Vec<FpVar<F>>, SynthesisError> {
|
||||
let five = FpVar::<F>::new_constant(cs.clone(), F::from(5u32))?;
|
||||
let z_i = z_i[0].clone();
|
||||
|
||||
Ok(vec![&z_i * &z_i * &z_i + &z_i + &five])
|
||||
}
|
||||
}
|
||||
|
||||
/// CustomFCircuit is a circuit that has the number of constraints specified in the
|
||||
/// `n_constraints` parameter. Note that the generated circuit will have very sparse matrices.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct CustomFCircuit<F: PrimeField> {
|
||||
_f: PhantomData<F>,
|
||||
pub n_constraints: usize,
|
||||
}
|
||||
impl<F: PrimeField> FCircuit<F> for CustomFCircuit<F> {
|
||||
type Params = usize;
|
||||
|
||||
fn new(params: Self::Params) -> Self {
|
||||
Self {
|
||||
_f: PhantomData,
|
||||
n_constraints: params,
|
||||
}
|
||||
}
|
||||
fn step_native(self, z_i: Vec<F>) -> Result<Vec<F>, Error> {
|
||||
let mut z_i1 = F::one();
|
||||
for _ in 0..self.n_constraints - 1 {
|
||||
z_i1 *= z_i[0];
|
||||
}
|
||||
Ok(vec![z_i1])
|
||||
}
|
||||
fn generate_step_constraints(
|
||||
self,
|
||||
cs: ConstraintSystemRef<F>,
|
||||
z_i: Vec<FpVar<F>>,
|
||||
) -> Result<Vec<FpVar<F>>, SynthesisError> {
|
||||
let mut z_i1 = FpVar::<F>::new_witness(cs.clone(), || Ok(F::one()))?;
|
||||
for _ in 0..self.n_constraints - 1 {
|
||||
z_i1 *= z_i[0].clone();
|
||||
}
|
||||
|
||||
Ok(vec![z_i1])
|
||||
}
|
||||
}
|
||||
|
||||
/// WrapperCircuit is a circuit that wraps any circuit that implements the FCircuit trait. This
|
||||
/// is used to test the `FCircuit.generate_step_constraints` method. This is a similar wrapping
|
||||
/// than the one done in the `AugmentedFCircuit`, but without adding all the extra constraints
|
||||
/// of the AugmentedF circuit logic, in order to run lighter tests when we're not interested in
|
||||
/// the the AugmentedF logic but in the wrapping of the circuits.
|
||||
pub struct WrapperCircuit<F: PrimeField, FC: FCircuit<F>> {
|
||||
pub FC: FC, // F circuit
|
||||
pub z_i: Option<Vec<F>>,
|
||||
pub z_i1: Option<Vec<F>>,
|
||||
}
|
||||
impl<F, FC> ConstraintSynthesizer<F> for WrapperCircuit<F, FC>
|
||||
where
|
||||
F: PrimeField,
|
||||
FC: FCircuit<F>,
|
||||
{
|
||||
fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
|
||||
let z_i = Vec::<FpVar<F>>::new_witness(cs.clone(), || {
|
||||
Ok(self.z_i.unwrap_or(vec![F::zero()]))
|
||||
})?;
|
||||
let z_i1 = Vec::<FpVar<F>>::new_input(cs.clone(), || {
|
||||
Ok(self.z_i1.unwrap_or(vec![F::zero()]))
|
||||
})?;
|
||||
let computed_z_i1 = self.FC.generate_step_constraints(cs.clone(), z_i.clone())?;
|
||||
|
||||
computed_z_i1.enforce_equal(&z_i1)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_testfcircuit() {
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
let F_circuit = CubicFCircuit::<Fr>::new(());
|
||||
|
||||
let wrapper_circuit = WrapperCircuit::<Fr, CubicFCircuit<Fr>> {
|
||||
FC: F_circuit,
|
||||
z_i: Some(vec![Fr::from(3_u32)]),
|
||||
z_i1: Some(vec![Fr::from(35_u32)]),
|
||||
};
|
||||
wrapper_circuit.generate_constraints(cs.clone()).unwrap();
|
||||
assert_eq!(cs.num_constraints(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_customtestfcircuit() {
|
||||
let cs = ConstraintSystem::<Fr>::new_ref();
|
||||
let n_constraints = 1000;
|
||||
let custom_circuit = CustomFCircuit::<Fr>::new(n_constraints);
|
||||
let z_i = vec![Fr::from(5_u32)];
|
||||
let wrapper_circuit = WrapperCircuit::<Fr, CustomFCircuit<Fr>> {
|
||||
FC: custom_circuit,
|
||||
z_i: Some(z_i.clone()),
|
||||
z_i1: Some(custom_circuit.step_native(z_i).unwrap()),
|
||||
};
|
||||
wrapper_circuit.generate_constraints(cs.clone()).unwrap();
|
||||
assert_eq!(cs.num_constraints(), n_constraints);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user