* Work * Tweak * Fmt * Work * Format + typo fixes * `no-std` fixavoid_assigned_value
@ -37,11 +37,7 @@ impl AllocationMode { |
|||||
|
|
||||
/// Specifies how variables of type `Self` should be allocated in a
|
/// Specifies how variables of type `Self` should be allocated in a
|
||||
/// `ConstraintSystem`.
|
/// `ConstraintSystem`.
|
||||
pub trait AllocVar<V, F: Field>
|
|
||||
where
|
|
||||
Self: Sized,
|
|
||||
V: ?Sized,
|
|
||||
{
|
|
||||
|
pub trait AllocVar<V: ?Sized, F: Field>: Sized {
|
||||
/// Allocates a new variable of type `Self` in the `ConstraintSystem` `cs`.
|
/// Allocates a new variable of type `Self` in the `ConstraintSystem` `cs`.
|
||||
/// The mode of allocation is decided by `mode`.
|
/// The mode of allocation is decided by `mode`.
|
||||
fn new_variable<T: Borrow<V>>(
|
fn new_variable<T: Borrow<V>>(
|
||||
@ -92,10 +88,56 @@ impl> AllocVar<[I], F> for Vec { |
|||||
) -> Result<Self, SynthesisError> {
|
) -> Result<Self, SynthesisError> {
|
||||
let ns = cs.into();
|
let ns = cs.into();
|
||||
let cs = ns.cs();
|
let cs = ns.cs();
|
||||
let mut vec = Vec::new();
|
|
||||
for value in f()?.borrow().iter() {
|
|
||||
vec.push(A::new_variable(cs.clone(), || Ok(value), mode)?);
|
|
||||
}
|
|
||||
Ok(vec)
|
|
||||
|
f().and_then(|v| {
|
||||
|
v.borrow()
|
||||
|
.iter()
|
||||
|
.map(|e| A::new_variable(cs.clone(), || Ok(e), mode))
|
||||
|
.collect()
|
||||
|
})
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
/// Dummy impl for `()`.
|
||||
|
impl<F: Field> AllocVar<(), F> for () {
|
||||
|
fn new_variable<T: Borrow<()>>(
|
||||
|
_cs: impl Into<Namespace<F>>,
|
||||
|
_f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||
|
_mode: AllocationMode,
|
||||
|
) -> Result<Self, SynthesisError> {
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
/// This blanket implementation just allocates variables in `Self`
|
||||
|
/// element by element.
|
||||
|
impl<I, F: Field, A: AllocVar<I, F>, const N: usize> AllocVar<[I; N], F> for [A; N] {
|
||||
|
fn new_variable<T: Borrow<[I; N]>>(
|
||||
|
cs: impl Into<Namespace<F>>,
|
||||
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||
|
mode: AllocationMode,
|
||||
|
) -> Result<Self, SynthesisError> {
|
||||
|
let ns = cs.into();
|
||||
|
let cs = ns.cs();
|
||||
|
f().map(|v| {
|
||||
|
let v = v.borrow();
|
||||
|
core::array::from_fn(|i| A::new_variable(cs.clone(), || Ok(&v[i]), mode).unwrap())
|
||||
|
})
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
/// This blanket implementation just allocates variables in `Self`
|
||||
|
/// element by element.
|
||||
|
impl<I, F: Field, A: AllocVar<I, F>, const N: usize> AllocVar<[I], F> for [A; N] {
|
||||
|
fn new_variable<T: Borrow<[I]>>(
|
||||
|
cs: impl Into<Namespace<F>>,
|
||||
|
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||
|
mode: AllocationMode,
|
||||
|
) -> Result<Self, SynthesisError> {
|
||||
|
let ns = cs.into();
|
||||
|
let cs = ns.cs();
|
||||
|
f().map(|v| {
|
||||
|
let v = v.borrow();
|
||||
|
core::array::from_fn(|i| A::new_variable(cs.clone(), || Ok(&v[i]), mode).unwrap())
|
||||
|
})
|
||||
}
|
}
|
||||
}
|
}
|
@ -0,0 +1,86 @@ |
|||||
|
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<F: Field> {
|
||||
|
/// 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<F>;
|
||||
|
|
||||
|
/// 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<Self::Value, SynthesisError>;
|
||||
|
}
|
||||
|
|
||||
|
impl<F: Field, T: R1CSVar<F>> R1CSVar<F> for [T] {
|
||||
|
type Value = Vec<T::Value>;
|
||||
|
|
||||
|
fn cs(&self) -> ConstraintSystemRef<F> {
|
||||
|
let mut result = ConstraintSystemRef::None;
|
||||
|
for var in self {
|
||||
|
result = var.cs().or(result);
|
||||
|
}
|
||||
|
result
|
||||
|
}
|
||||
|
|
||||
|
fn value(&self) -> Result<Self::Value, SynthesisError> {
|
||||
|
let mut result = Vec::new();
|
||||
|
for var in self {
|
||||
|
result.push(var.value()?);
|
||||
|
}
|
||||
|
Ok(result)
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl<'a, F: Field, T: 'a + R1CSVar<F>> R1CSVar<F> for &'a T {
|
||||
|
type Value = T::Value;
|
||||
|
|
||||
|
fn cs(&self) -> ConstraintSystemRef<F> {
|
||||
|
(*self).cs()
|
||||
|
}
|
||||
|
|
||||
|
fn value(&self) -> Result<Self::Value, SynthesisError> {
|
||||
|
(*self).value()
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl<F: Field, T: R1CSVar<F>, const N: usize> R1CSVar<F> for [T; N] {
|
||||
|
type Value = [T::Value; N];
|
||||
|
|
||||
|
fn cs(&self) -> ConstraintSystemRef<F> {
|
||||
|
let mut result = ConstraintSystemRef::None;
|
||||
|
for var in self {
|
||||
|
result = var.cs().or(result);
|
||||
|
}
|
||||
|
result
|
||||
|
}
|
||||
|
|
||||
|
fn value(&self) -> Result<Self::Value, SynthesisError> {
|
||||
|
Ok(core::array::from_fn(|i| self[i].value().unwrap()))
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
impl<F: Field> R1CSVar<F> for () {
|
||||
|
type Value = ();
|
||||
|
|
||||
|
fn cs(&self) -> ConstraintSystemRef<F> {
|
||||
|
ConstraintSystemRef::None
|
||||
|
}
|
||||
|
|
||||
|
fn value(&self) -> Result<Self::Value, SynthesisError> {
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
}
|