arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/src/alloc.rs
src/alloc.rsRaw
  1use crate::Vec;
  2use ark_ff::Field;
  3use ark_relations::r1cs::{Namespace, SynthesisError};
  4use core::borrow::Borrow;
  5
  6/// Describes the mode that a variable should be allocated in within
  7/// a `ConstraintSystem`.
  8#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
  9pub enum AllocationMode {
 10    /// Indicate to the `ConstraintSystem` that the high-level variable should
 11    /// be allocated as a constant. That is, no `Variable`s should be
 12    /// generated.
 13    Constant = 0,
 14
 15    /// Indicate to the `ConstraintSystem` that the high-level variable should
 16    /// be allocated as a public input to the `ConstraintSystem`.
 17    Input = 1,
 18
 19    /// Indicate to the `ConstraintSystem` that the high-level variable should
 20    /// be allocated as a private witness to the `ConstraintSystem`.
 21    Witness = 2,
 22}
 23
 24impl AllocationMode {
 25    /// Outputs the maximum according to the relation `Constant < Input <
 26    /// Witness`.
 27    pub fn max(&self, other: Self) -> Self {
 28        use AllocationMode::*;
 29        match (self, other) {
 30            (Constant, _) => other,
 31            (Input, Constant) => *self,
 32            (Input, _) => other,
 33            (Witness, _) => *self,
 34        }
 35    }
 36}
 37
 38/// Specifies how variables of type `Self` should be allocated in a
 39/// `ConstraintSystem`.
 40pub trait AllocVar<V, F: Field>
 41where
 42    Self: Sized,
 43    V: ?Sized,
 44{
 45    /// Allocates a new variable of type `Self` in the `ConstraintSystem` `cs`.
 46    /// The mode of allocation is decided by `mode`.
 47    fn new_variable<T: Borrow<V>>(
 48        cs: impl Into<Namespace<F>>,
 49        f: impl FnOnce() -> Result<T, SynthesisError>,
 50        mode: AllocationMode,
 51    ) -> Result<Self, SynthesisError>;
 52
 53    /// Allocates a new constant of type `Self` in the `ConstraintSystem` `cs`.
 54    ///
 55    /// This should *not* allocate any new variables or constraints in `cs`.
 56    #[tracing::instrument(target = "r1cs", skip(cs, t))]
 57    fn new_constant(
 58        cs: impl Into<Namespace<F>>,
 59        t: impl Borrow<V>,
 60    ) -> Result<Self, SynthesisError> {
 61        Self::new_variable(cs, || Ok(t), AllocationMode::Constant)
 62    }
 63
 64    /// Allocates a new public input of type `Self` in the `ConstraintSystem`
 65    /// `cs`.
 66    #[tracing::instrument(target = "r1cs", skip(cs, f))]
 67    fn new_input<T: Borrow<V>>(
 68        cs: impl Into<Namespace<F>>,
 69        f: impl FnOnce() -> Result<T, SynthesisError>,
 70    ) -> Result<Self, SynthesisError> {
 71        Self::new_variable(cs, f, AllocationMode::Input)
 72    }
 73
 74    /// Allocates a new private witness of type `Self` in the `ConstraintSystem`
 75    /// `cs`.
 76    #[tracing::instrument(target = "r1cs", skip(cs, f))]
 77    fn new_witness<T: Borrow<V>>(
 78        cs: impl Into<Namespace<F>>,
 79        f: impl FnOnce() -> Result<T, SynthesisError>,
 80    ) -> Result<Self, SynthesisError> {
 81        Self::new_variable(cs, f, AllocationMode::Witness)
 82    }
 83}
 84
 85/// This blanket implementation just allocates variables in `Self`
 86/// element by element.
 87impl<I, F: Field, A: AllocVar<I, F>> AllocVar<[I], F> for Vec<A> {
 88    fn new_variable<T: Borrow<[I]>>(
 89        cs: impl Into<Namespace<F>>,
 90        f: impl FnOnce() -> Result<T, SynthesisError>,
 91        mode: AllocationMode,
 92    ) -> Result<Self, SynthesisError> {
 93        let ns = cs.into();
 94        let cs = ns.cs();
 95        let mut vec = Vec::new();
 96        for value in f()?.borrow().iter() {
 97            vec.push(A::new_variable(cs.clone(), || Ok(value), mode)?);
 98        }
 99        Ok(vec)
100    }
101}