Skip to content

Commit

Permalink
Reduce time for native computation in prove_step (#184)
Browse files Browse the repository at this point in the history
* Reduce native computation by removing the unnecessary `step_native` call

* It is unnecessary to compute `x` for `CycleFoldCircuit` outside the circuit

* Remove `step_native` from `FCircuit`

* Rationale behind the check of public inputs against witnesses

* Format

* Fix examples
  • Loading branch information
winderica authored Dec 17, 2024
1 parent 659b909 commit 0cfc228
Show file tree
Hide file tree
Showing 18 changed files with 291 additions and 648 deletions.
33 changes: 15 additions & 18 deletions examples/external_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ use ark_bn254::{constraints::GVar, Bn254, Fr, G1Projective as Projective};
use ark_crypto_primitives::{
crh::{
poseidon::constraints::{CRHGadget, CRHParametersVar},
poseidon::CRH,
CRHScheme, CRHSchemeGadget,
CRHSchemeGadget,
},
sponge::{poseidon::PoseidonConfig, Absorb},
};
Expand Down Expand Up @@ -88,20 +87,6 @@ where
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<F>,
external_inputs: Vec<F>,
) -> Result<Vec<F>, Error> {
let hash_input: [F; 2] = [z_i[0], external_inputs[0]];
let h = CRH::<F>::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(
Expand All @@ -123,21 +108,33 @@ where
#[cfg(test)]
pub mod tests {
use super::*;
use ark_crypto_primitives::crh::{poseidon::CRH, CRHScheme};
use ark_r1cs_std::R1CSVar;
use ark_relations::r1cs::ConstraintSystem;

fn external_inputs_step_native<F: PrimeField + Absorb>(
z_i: Vec<F>,
external_inputs: Vec<F>,
poseidon_config: &PoseidonConfig<F>,
) -> Vec<F> {
let hash_input: [F; 2] = [z_i[0], external_inputs[0]];
let h = CRH::<F>::evaluate(poseidon_config, hash_input).unwrap();
vec![h]
}

// test to check that the ExternalInputsCircuit computes the same values inside and outside the circuit
#[test]
fn test_f_circuit() -> Result<(), Error> {
let poseidon_config = poseidon_canonical_config::<Fr>();

let cs = ConstraintSystem::<Fr>::new_ref();

let circuit = ExternalInputsCircuit::<Fr>::new(poseidon_config)?;
let circuit = ExternalInputsCircuit::<Fr>::new(poseidon_config.clone())?;
let z_i = vec![Fr::from(1_u32)];
let external_inputs = vec![Fr::from(3_u32)];

let z_i1 = circuit.step_native(0, z_i.clone(), external_inputs.clone())?;
let z_i1 =
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))?;
Expand Down
8 changes: 0 additions & 8 deletions examples/full_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,6 @@ impl<F: PrimeField> FCircuit<F> for CubicFCircuit<F> {
fn external_inputs_len(&self) -> usize {
0
}
fn step_native(
&self,
_i: usize,
z_i: Vec<F>,
_external_inputs: 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>,
Expand Down
30 changes: 11 additions & 19 deletions examples/multi_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,6 @@ impl<F: PrimeField> FCircuit<F> for MultiInputsFCircuit<F> {
fn external_inputs_len(&self) -> usize {
0
}

/// 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<F>,
_external_inputs: Vec<F>,
) -> Result<Vec<F>, 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,
Expand Down Expand Up @@ -86,6 +68,16 @@ pub mod tests {
use ark_r1cs_std::{alloc::AllocVar, R1CSVar};
use ark_relations::r1cs::ConstraintSystem;

fn multi_inputs_step_native<F: PrimeField>(z_i: Vec<F>) -> Vec<F> {
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);

vec![a, b, c, d, e]
}

// test to check that the MultiInputsFCircuit computes the same values inside and outside the circuit
#[test]
fn test_f_circuit() -> Result<(), Error> {
Expand All @@ -100,7 +92,7 @@ pub mod tests {
Fr::from(1_u32),
];

let z_i1 = circuit.step_native(0, z_i.clone(), vec![])?;
let z_i1 = multi_inputs_step_native(z_i.clone());

let z_iVar = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(z_i))?;
let computed_z_i1Var =
Expand Down
35 changes: 13 additions & 22 deletions examples/sha256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
#![allow(clippy::upper_case_acronyms)]

use ark_crypto_primitives::crh::{
sha256::{
constraints::{Sha256Gadget, UnitVar},
Sha256,
},
CRHScheme, CRHSchemeGadget,
sha256::constraints::{Sha256Gadget, UnitVar},
CRHSchemeGadget,
};
use ark_ff::{BigInteger, PrimeField, ToConstraintField};
use ark_ff::PrimeField;
use ark_r1cs_std::{
convert::{ToBytesGadget, ToConstraintFieldGadget},
fields::fp::FpVar,
Expand Down Expand Up @@ -49,21 +46,6 @@ impl<F: PrimeField> FCircuit<F> for Sha256FCircuit<F> {
fn external_inputs_len(&self) -> usize {
0
}

/// 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<F>,
_external_inputs: Vec<F>,
) -> Result<Vec<F>, Error> {
let out_bytes = Sha256::evaluate(&(), z_i[0].into_bigint().to_bytes_le()).unwrap();
let out: Vec<F> = out_bytes.to_field_elements().unwrap();

Ok(vec![out[0]])
}

/// generates the constraints for the step of F for the given z_i
fn generate_step_constraints(
&self,
Expand All @@ -83,9 +65,18 @@ impl<F: PrimeField> FCircuit<F> for Sha256FCircuit<F> {
#[cfg(test)]
pub mod tests {
use super::*;
use ark_crypto_primitives::crh::{sha256::Sha256, CRHScheme};
use ark_ff::{BigInteger, ToConstraintField};
use ark_r1cs_std::{alloc::AllocVar, R1CSVar};
use ark_relations::r1cs::ConstraintSystem;

fn sha256_step_native<F: PrimeField>(z_i: Vec<F>) -> Vec<F> {
let out_bytes = Sha256::evaluate(&(), z_i[0].into_bigint().to_bytes_le()).unwrap();
let out: Vec<F> = out_bytes.to_field_elements().unwrap();

vec![out[0]]
}

// test to check that the Sha256FCircuit computes the same values inside and outside the circuit
#[test]
fn test_f_circuit() -> Result<(), Error> {
Expand All @@ -94,7 +85,7 @@ pub mod tests {
let circuit = Sha256FCircuit::<Fr>::new(())?;
let z_i = vec![Fr::from(1_u32)];

let z_i1 = circuit.step_native(0, z_i.clone(), vec![])?;
let z_i1 = sha256_step_native(z_i.clone());

let z_iVar = Vec::<FpVar<Fr>>::new_witness(cs.clone(), || Ok(z_i))?;
let computed_z_i1Var =
Expand Down
Loading

0 comments on commit 0cfc228

Please sign in to comment.