use ark_ff::Field; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; use ark_std::vec::Vec; /// This trait describes some core functionality that is common to high-level /// variables, such as `Boolean`s, `FieldVar`s, `GroupVar`s, etc. pub trait R1CSVar { /// The type of the "native" value that `Self` represents in the constraint /// system. type Value: core::fmt::Debug + Eq + Clone; /// Returns the underlying `ConstraintSystemRef`. /// /// If `self` is a constant value, then this *must* return /// `ark_relations::r1cs::ConstraintSystemRef::None`. fn cs(&self) -> ConstraintSystemRef; /// Returns `true` if `self` is a circuit-generation-time constant. fn is_constant(&self) -> bool { self.cs().is_none() } /// Returns the value that is assigned to `self` in the underlying /// `ConstraintSystem`. fn value(&self) -> Result; } impl> R1CSVar for [T] { type Value = Vec; fn cs(&self) -> ConstraintSystemRef { let mut result = ConstraintSystemRef::None; for var in self { result = var.cs().or(result); } result } fn value(&self) -> Result { let mut result = Vec::new(); for var in self { result.push(var.value()?); } Ok(result) } } impl<'a, F: Field, T: 'a + R1CSVar> R1CSVar for &'a T { type Value = T::Value; fn cs(&self) -> ConstraintSystemRef { (*self).cs() } fn value(&self) -> Result { (*self).value() } } impl, const N: usize> R1CSVar for [T; N] { type Value = [T::Value; N]; fn cs(&self) -> ConstraintSystemRef { let mut result = ConstraintSystemRef::None; for var in self { result = var.cs().or(result); } result } fn value(&self) -> Result { Ok(core::array::from_fn(|i| self[i].value().unwrap())) } } impl R1CSVar for () { type Value = (); fn cs(&self) -> ConstraintSystemRef { ConstraintSystemRef::None } fn value(&self) -> Result { Ok(()) } }