Skip to content

Commit

Permalink
Update the FCircuit trait, so that it supports custom data structures…
Browse files Browse the repository at this point in the history
… for the external inputs. (#191)

* Update the FCircuit trait, so that it supports custom data structures for the external inputs.

This also eliminates the need of having the `external_inputs_len` method in the `FCircuit`.

The motivation for this change is that in most practical use cases, the
external inputs have a not-naive structure, and the old interface required that
to convert the external inputs structure into a vector of finite field
elements, which inside the FCircuit would be converted back into a custom data
structure. This is specially tedious when dealing with curve points, which
converting them from point to field elements and back to the point (both
outside (rust native) and inside the circuit (constraints)) is a bit
cumbersome.  With this update, it's much more straight forward to define the
FCircuit with custom external inputs data structures.

For the experimental-frontends, the external inputs keep being an array of field elements.

* remove Default from FCircuit::ExternalInputsVar, remove VecF & VecFpVar in examples/external_inputs.rs
  • Loading branch information
arnaucube authored Dec 27, 2024
1 parent 1ef933a commit c6f1a24
Show file tree
Hide file tree
Showing 35 changed files with 319 additions and 294 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
Cargo.lock

# Circom generated files
frontends/src/circom/test_folder/*_js/
experimental-frontends/src/circom/test_folder/*_js/
*.r1cs
*.sym

# Noir generated files
frontends/src/noir/test_folder/*/target/*
experimental-frontends/src/noir/test_folder/*/target/*

# generated contracts data
solidity-verifiers/generated
Expand Down
4 changes: 2 additions & 2 deletions benches/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub(crate) fn bench_ivc_opt<

// warmup steps
for _ in 0..5 {
fs.prove_step(rng, vec![], None)?;
fs.prove_step(rng, (), None)?;
}

let mut group = c.benchmark_group(format!(
Expand All @@ -38,7 +38,7 @@ pub(crate) fn bench_ivc_opt<
));
group.significance_level(0.1).sample_size(10);
group.bench_function("prove_step", |b| {
b.iter(|| -> Result<_, _> { black_box(fs.clone()).prove_step(rng, vec![], None) })
b.iter(|| -> Result<_, _> { black_box(fs.clone()).prove_step(rng, (), None) })
});

// verify the IVCProof
Expand Down
14 changes: 8 additions & 6 deletions examples/circom_full_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use ark_grumpkin::Projective as G2;
use std::path::PathBuf;
use std::time::Instant;

use experimental_frontends::circom::CircomFCircuit;
use experimental_frontends::{circom::CircomFCircuit, utils::VecF};
use folding_schemes::{
commitment::{kzg::KZG, pedersen::Pedersen},
folding::{
Expand Down Expand Up @@ -64,14 +64,16 @@ fn main() -> Result<(), Error> {
"./experimental-frontends/src/circom/test_folder/with_external_inputs_js/with_external_inputs.wasm",
);

let f_circuit_params = (r1cs_path.into(), wasm_path.into(), 1, 2);
let f_circuit = CircomFCircuit::<Fr>::new(f_circuit_params)?;
let f_circuit_params = (r1cs_path.into(), wasm_path.into(), 1); // state len = 1
const EXT_INP_LEN: usize = 2; // external inputs len = 2
let f_circuit = CircomFCircuit::<Fr, EXT_INP_LEN>::new(f_circuit_params)?;

pub type N = Nova<G1, G2, CircomFCircuit<Fr>, KZG<'static, Bn254>, Pedersen<G2>, false>;
pub type N =
Nova<G1, G2, CircomFCircuit<Fr, EXT_INP_LEN>, KZG<'static, Bn254>, Pedersen<G2>, false>;
pub type D = DeciderEth<
G1,
G2,
CircomFCircuit<Fr>,
CircomFCircuit<Fr, EXT_INP_LEN>,
KZG<'static, Bn254>,
Pedersen<G2>,
Groth16<Bn254>,
Expand All @@ -94,7 +96,7 @@ fn main() -> Result<(), Error> {
// 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(rng, external_inputs_at_step.clone(), None)?;
nova.prove_step(rng, VecF(external_inputs_at_step.clone()), None)?;
println!("Nova::prove_step {}: {:?}", i, start.elapsed());
}

Expand Down
22 changes: 12 additions & 10 deletions examples/external_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ where
F: Absorb,
{
type Params = PoseidonConfig<F>;
type ExternalInputs = [F; 1];
type ExternalInputsVar = [FpVar<F>; 1];

fn new(params: Self::Params) -> Result<Self, Error> {
Ok(Self {
Expand All @@ -84,17 +86,14 @@ where
fn state_len(&self) -> usize {
1
}
fn external_inputs_len(&self) -> usize {
1
}
/// 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(
&self,
cs: ConstraintSystemRef<F>,
_i: usize,
z_i: Vec<FpVar<F>>,
external_inputs: Vec<FpVar<F>>,
external_inputs: Self::ExternalInputsVar,
) -> Result<Vec<FpVar<F>>, SynthesisError> {
let crh_params =
CRHParametersVar::<F>::new_constant(cs.clone(), self.poseidon_config.clone())?;
Expand Down Expand Up @@ -137,7 +136,10 @@ pub mod tests {
external_inputs_step_native(z_i.clone(), external_inputs.clone(), &poseidon_config);

let z_iVar = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(z_i))?;
let external_inputsVar = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(external_inputs))?;
let external_inputsVar: [FpVar<Fr>; 1] =
Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(external_inputs))?
.try_into()
.unwrap();

let computed_z_i1Var =
circuit.generate_step_constraints(cs.clone(), 0, z_iVar, external_inputsVar)?;
Expand All @@ -153,11 +155,11 @@ fn main() -> Result<(), Error> {

// prepare the external inputs to be used at each folding step
let external_inputs = vec![
vec![Fr::from(3_u32)],
vec![Fr::from(33_u32)],
vec![Fr::from(73_u32)],
vec![Fr::from(103_u32)],
vec![Fr::from(125_u32)],
[Fr::from(3_u32)],
[Fr::from(33_u32)],
[Fr::from(73_u32)],
[Fr::from(103_u32)],
[Fr::from(125_u32)],
];
assert_eq!(external_inputs.len(), num_steps);

Expand Down
10 changes: 5 additions & 5 deletions examples/full_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,21 @@ pub struct CubicFCircuit<F: PrimeField> {
}
impl<F: PrimeField> FCircuit<F> for CubicFCircuit<F> {
type Params = ();
type ExternalInputs = ();
type ExternalInputsVar = ();

fn new(_params: Self::Params) -> Result<Self, Error> {
Ok(Self { _f: PhantomData })
}
fn state_len(&self) -> usize {
1
}
fn external_inputs_len(&self) -> usize {
0
}
fn generate_step_constraints(
&self,
cs: ConstraintSystemRef<F>,
_i: usize,
z_i: Vec<FpVar<F>>,
_external_inputs: Vec<FpVar<F>>,
_external_inputs: Self::ExternalInputsVar,
) -> Result<Vec<FpVar<F>>, SynthesisError> {
let five = FpVar::<F>::new_constant(cs.clone(), F::from(5u32))?;
let z_i = z_i[0].clone();
Expand Down Expand Up @@ -96,7 +96,7 @@ fn main() -> Result<(), Error> {
// run n steps of the folding iteration
for i in 0..n_steps {
let start = Instant::now();
nova.prove_step(rng, vec![], None)?;
nova.prove_step(rng, (), None)?;
println!("Nova::prove_step {}: {:?}", i, start.elapsed());
}

Expand Down
11 changes: 5 additions & 6 deletions examples/multi_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,22 @@ pub struct MultiInputsFCircuit<F: PrimeField> {
}
impl<F: PrimeField> FCircuit<F> for MultiInputsFCircuit<F> {
type Params = ();
type ExternalInputs = ();
type ExternalInputsVar = ();

fn new(_params: Self::Params) -> Result<Self, Error> {
Ok(Self { _f: PhantomData })
}
fn state_len(&self) -> usize {
5
}
fn external_inputs_len(&self) -> usize {
0
}
/// generates the constraints for the step of F for the given z_i
fn generate_step_constraints(
&self,
cs: ConstraintSystemRef<F>,
_i: usize,
z_i: Vec<FpVar<F>>,
_external_inputs: Vec<FpVar<F>>,
_external_inputs: Self::ExternalInputsVar,
) -> Result<Vec<FpVar<F>>, SynthesisError> {
let four = FpVar::<F>::new_constant(cs.clone(), F::from(4u32))?;
let forty = FpVar::<F>::new_constant(cs.clone(), F::from(40u32))?;
Expand Down Expand Up @@ -96,7 +95,7 @@ pub mod tests {

let z_iVar = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(z_i))?;
let computed_z_i1Var =
circuit.generate_step_constraints(cs.clone(), 0, z_iVar.clone(), vec![])?;
circuit.generate_step_constraints(cs.clone(), 0, z_iVar.clone(), ())?;
assert_eq!(computed_z_i1Var.value()?, z_i1);
Ok(())
}
Expand Down Expand Up @@ -140,7 +139,7 @@ fn main() -> Result<(), Error> {
// compute a step of the IVC
for i in 0..num_steps {
let start = Instant::now();
folding_scheme.prove_step(rng, vec![], None)?;
folding_scheme.prove_step(rng, (), None)?;
println!("Nova::prove_step {}: {:?}", i, start.elapsed());
}

Expand Down
21 changes: 14 additions & 7 deletions examples/noir_full_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use ark_bn254::{Bn254, Fr, G1Projective as G1};
use ark_groth16::Groth16;
use ark_grumpkin::Projective as G2;

use experimental_frontends::noir::NoirFCircuit;
use experimental_frontends::{noir::NoirFCircuit, utils::VecF};
use folding_schemes::{
commitment::{kzg::KZG, pedersen::Pedersen},
folding::{
Expand Down Expand Up @@ -42,16 +42,23 @@ fn main() -> Result<(), Error> {
let z_0 = vec![Fr::from(1)];

// initialize the noir fcircuit
let f_circuit = NoirFCircuit::new((
const EXT_INP_LEN: usize = 0;
let f_circuit = NoirFCircuit::<Fr, EXT_INP_LEN>::new((
Path::new("./experimental-frontends/src/noir/test_folder/test_mimc/target/test_mimc.json")
.into(),
1,
0,
))?;

pub type N = Nova<G1, G2, NoirFCircuit<Fr>, KZG<'static, Bn254>, Pedersen<G2>>;
pub type D =
DeciderEth<G1, G2, NoirFCircuit<Fr>, KZG<'static, Bn254>, Pedersen<G2>, Groth16<Bn254>, N>;
pub type N = Nova<G1, G2, NoirFCircuit<Fr, EXT_INP_LEN>, KZG<'static, Bn254>, Pedersen<G2>>;
pub type D = DeciderEth<
G1,
G2,
NoirFCircuit<Fr, EXT_INP_LEN>,
KZG<'static, Bn254>,
Pedersen<G2>,
Groth16<Bn254>,
N,
>;

let poseidon_config = poseidon_canonical_config::<Fr>();
let mut rng = ark_std::rand::rngs::OsRng;
Expand All @@ -69,7 +76,7 @@ fn main() -> Result<(), Error> {
// run n steps of the folding iteration
for i in 0..5 {
let start = Instant::now();
nova.prove_step(rng, vec![], None)?;
nova.prove_step(rng, VecF(vec![]), None)?;
println!("Nova::prove_step {}: {:?}", i, start.elapsed());
}
// verify the last IVC proof
Expand Down
20 changes: 13 additions & 7 deletions examples/noname_full_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use noname::backends::r1cs::R1csBn254Field;
use ark_groth16::Groth16;
use ark_grumpkin::Projective as G2;

use experimental_frontends::noname::NonameFCircuit;
use experimental_frontends::{noname::NonameFCircuit, utils::VecF};
use folding_schemes::{
commitment::{kzg::KZG, pedersen::Pedersen},
folding::{
Expand Down Expand Up @@ -58,15 +58,21 @@ fn main() -> Result<(), Error> {
];

// initialize the noname circuit
let f_circuit_params = (NONAME_CIRCUIT_EXTERNAL_INPUTS.to_owned(), 2, 2);
let f_circuit = NonameFCircuit::<Fr, R1csBn254Field>::new(f_circuit_params)?;
let f_circuit_params = (NONAME_CIRCUIT_EXTERNAL_INPUTS.to_owned(), 2); // state len = 2
const EXT_INP_LEN: usize = 2;
let f_circuit = NonameFCircuit::<Fr, R1csBn254Field, EXT_INP_LEN>::new(f_circuit_params)?;

pub type N =
Nova<G1, G2, NonameFCircuit<Fr, R1csBn254Field>, KZG<'static, Bn254>, Pedersen<G2>>;
pub type N = Nova<
G1,
G2,
NonameFCircuit<Fr, R1csBn254Field, EXT_INP_LEN>,
KZG<'static, Bn254>,
Pedersen<G2>,
>;
pub type D = DeciderEth<
G1,
G2,
NonameFCircuit<Fr, R1csBn254Field>,
NonameFCircuit<Fr, R1csBn254Field, EXT_INP_LEN>,
KZG<'static, Bn254>,
Pedersen<G2>,
Groth16<Bn254>,
Expand All @@ -89,7 +95,7 @@ fn main() -> Result<(), Error> {
// 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(rng, external_inputs_at_step.clone(), None)?;
nova.prove_step(rng, VecF(external_inputs_at_step.clone()), None)?;
println!("Nova::prove_step {}: {:?}", i, start.elapsed());
}

Expand Down
11 changes: 5 additions & 6 deletions examples/sha256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,22 @@ pub struct Sha256FCircuit<F: PrimeField> {
}
impl<F: PrimeField> FCircuit<F> for Sha256FCircuit<F> {
type Params = ();
type ExternalInputs = ();
type ExternalInputsVar = ();

fn new(_params: Self::Params) -> Result<Self, Error> {
Ok(Self { _f: PhantomData })
}
fn state_len(&self) -> usize {
1
}
fn external_inputs_len(&self) -> usize {
0
}
/// generates the constraints for the step of F for the given z_i
fn generate_step_constraints(
&self,
_cs: ConstraintSystemRef<F>,
_i: usize,
z_i: Vec<FpVar<F>>,
_external_inputs: Vec<FpVar<F>>,
_external_inputs: Self::ExternalInputsVar,
) -> Result<Vec<FpVar<F>>, SynthesisError> {
let unit_var = UnitVar::default();
let out_bytes = Sha256Gadget::evaluate(&unit_var, &z_i[0].to_bytes_le()?)?;
Expand Down Expand Up @@ -89,7 +88,7 @@ pub mod tests {

let z_iVar = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(z_i))?;
let computed_z_i1Var =
circuit.generate_step_constraints(cs.clone(), 0, z_iVar.clone(), vec![])?;
circuit.generate_step_constraints(cs.clone(), 0, z_iVar.clone(), ())?;
assert_eq!(computed_z_i1Var.value()?, z_i1);
Ok(())
}
Expand Down Expand Up @@ -126,7 +125,7 @@ fn main() -> Result<(), Error> {
// compute a step of the IVC
for i in 0..num_steps {
let start = Instant::now();
folding_scheme.prove_step(rng, vec![], None)?;
folding_scheme.prove_step(rng, (), None)?;
println!("Nova::prove_step {}: {:?}", i, start.elapsed());
}

Expand Down
Loading

0 comments on commit c6f1a24

Please sign in to comment.