Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Dec 27, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
remove Default from FCircuit::ExternalInputsVar, remove VecF & VecFpV…
…ar in examples/external_inputs.rs
arnaucube committed Dec 27, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 7682fe0fa190fa3a229eb5e5d5e7d8e35e034734
66 changes: 15 additions & 51 deletions examples/external_inputs.rs
Original file line number Diff line number Diff line change
@@ -74,8 +74,8 @@ where
F: Absorb,
{
type Params = PoseidonConfig<F>;
type ExternalInputs = VecF<F>;
type ExternalInputsVar = VecFpVar<F>;
type ExternalInputs = [F; 1];
type ExternalInputsVar = [FpVar<F>; 1];

fn new(params: Self::Params) -> Result<Self, Error> {
Ok(Self {
@@ -95,49 +95,14 @@ where
z_i: Vec<FpVar<F>>,
external_inputs: Self::ExternalInputsVar,
) -> Result<Vec<FpVar<F>>, SynthesisError> {
let ei: VecFpVar<F> = external_inputs.into();
let crh_params =
CRHParametersVar::<F>::new_constant(cs.clone(), self.poseidon_config.clone())?;
let hash_input: [FpVar<F>; 2] = [z_i[0].clone(), ei.0[0].clone()];
let hash_input: [FpVar<F>; 2] = [z_i[0].clone(), external_inputs[0].clone()];
let h = CRHGadget::<F>::evaluate(&crh_params, &hash_input)?;
Ok(vec![h])
}
}

#[derive(Clone, Debug)]
pub struct VecF<F: PrimeField>(Vec<F>);
impl<F: PrimeField> Default for VecF<F> {
fn default() -> Self {
VecF(vec![F::zero()])
}
}

use ark_r1cs_std::alloc::AllocationMode;
use ark_relations::r1cs::Namespace;
use core::borrow::Borrow;
#[derive(Clone, Debug)]
pub struct VecFpVar<F: PrimeField>(Vec<FpVar<F>>);
impl<F: PrimeField> AllocVar<VecF<F>, F> for VecFpVar<F> {
fn new_variable<T: Borrow<VecF<F>>>(
cs: impl Into<Namespace<F>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
mode: AllocationMode,
) -> Result<Self, SynthesisError> {
f().and_then(|val| {
let cs = cs.into();

let v = Vec::<FpVar<F>>::new_variable(cs.clone(), || Ok(val.borrow().0.clone()), mode)?;

Ok(VecFpVar(v))
})
}
}
impl<F: PrimeField> Default for VecFpVar<F> {
fn default() -> Self {
VecFpVar(vec![FpVar::<F>::Constant(F::zero())])
}
}

/// cargo test --example external_inputs
#[cfg(test)]
pub mod tests {
@@ -171,14 +136,13 @@ 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 computed_z_i1Var = circuit.generate_step_constraints(
cs.clone(),
0,
z_iVar,
VecFpVar(external_inputsVar),
)?;
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)?;
assert_eq!(computed_z_i1Var.value()?, z_i1);
Ok(())
}
@@ -191,11 +155,11 @@ fn main() -> Result<(), Error> {

// prepare the external inputs to be used at each folding step
let external_inputs = vec![
VecF(vec![Fr::from(3_u32)]),
VecF(vec![Fr::from(33_u32)]),
VecF(vec![Fr::from(73_u32)]),
VecF(vec![Fr::from(103_u32)]),
VecF(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);

2 changes: 1 addition & 1 deletion folding-schemes/src/folding/protogalaxy/mod.rs
Original file line number Diff line number Diff line change
@@ -567,7 +567,7 @@ where
cs.clone(),
0,
Vec::new_witness(cs.clone(), || Ok(vec![Zero::zero(); state_len]))?,
FC::ExternalInputsVar::default(),
FC::ExternalInputsVar::new_witness(cs.clone(), || Ok(FC::ExternalInputs::default()))?,
)?;
let step_constraints = cs.num_constraints();

6 changes: 3 additions & 3 deletions folding-schemes/src/frontend/mod.rs
Original file line number Diff line number Diff line change
@@ -12,12 +12,12 @@ pub mod utils;
/// 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.
/// implementation for the `ExternalInputs` returns the initialized data structure (ie. if the type
/// contains a vector, it is initialized at the expected length).
pub trait FCircuit<F: PrimeField>: Clone + Debug {
type Params: Debug;
type ExternalInputs: Clone + Default + Debug;
type ExternalInputsVar: Clone + Default + Debug + AllocVar<Self::ExternalInputs, F>;
type ExternalInputsVar: Clone + Debug + AllocVar<Self::ExternalInputs, F>;

/// returns a new FCircuit instance
fn new(params: Self::Params) -> Result<Self, Error>;
11 changes: 5 additions & 6 deletions folding-schemes/src/frontend/utils.rs
Original file line number Diff line number Diff line change
@@ -146,12 +146,11 @@ impl<F: PrimeField, FC: FCircuit<F>> ConstraintSynthesizer<F> for WrapperCircuit
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(),
0,
z_i.clone(),
FC::ExternalInputsVar::default(),
)?;
let external_inputs =
FC::ExternalInputsVar::new_input(cs.clone(), || Ok(FC::ExternalInputs::default()))?;
let computed_z_i1 =
self.FC
.generate_step_constraints(cs.clone(), 0, z_i.clone(), external_inputs)?;

use ark_r1cs_std::eq::EqGadget;
computed_z_i1.enforce_equal(&z_i1)?;