You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

93 lines
3.2 KiB

use crate::Vec;
use algebra::Field;
use core::borrow::Borrow;
use r1cs_core::{Namespace, SynthesisError};
/// Describes the mode that a variable should be allocated in within
/// a `ConstraintSystem`.
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
pub enum AllocationMode {
/// Indicate to the `ConstraintSystem` that the high-level variable should
/// be allocated as a constant. That is, no `Variable`s should be
/// generated.
Constant = 0,
/// Indicate to the `ConstraintSystem` that the high-level variable should
/// be allocated as a public input to the `ConstraintSystem`.
Input = 1,
/// Indicate to the `ConstraintSystem` that the high-level variable should
/// be allocated as a private witness to the `ConstraintSystem`.
Witness = 2,
}
impl AllocationMode {
/// Outputs the maximum according to the relation `Constant < Input < Witness`.
pub fn max(&self, other: Self) -> Self {
use AllocationMode::*;
match (self, other) {
(Constant, _) => other,
(Input, Constant) => *self,
(Input, _) => other,
(Witness, _) => *self,
}
}
}
/// Specifies how variables of type `Self` should be allocated in a `ConstraintSystem`.
pub trait AllocVar<V, F: Field>
where
Self: Sized,
V: ?Sized,
{
/// Allocates a new variable of type `Self` in the `ConstraintSystem`.
/// The mode of allocation is decided by `mode`.
fn new_variable<T: Borrow<V>>(
cs: impl Into<Namespace<F>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
mode: AllocationMode,
) -> Result<Self, SynthesisError>;
/// Allocates a new constant of type `Self` in the `ConstraintSystem`.
#[tracing::instrument(target = "r1cs", skip(cs, t))]
fn new_constant(
cs: impl Into<Namespace<F>>,
t: impl Borrow<V>,
) -> Result<Self, SynthesisError> {
Self::new_variable(cs, || Ok(t), AllocationMode::Constant)
}
/// Allocates a new public input of type `Self` in the `ConstraintSystem`.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_input<T: Borrow<V>>(
cs: impl Into<Namespace<F>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
) -> Result<Self, SynthesisError> {
Self::new_variable(cs, f, AllocationMode::Input)
}
/// Allocates a new private witness of type `Self` in the `ConstraintSystem`.
#[tracing::instrument(target = "r1cs", skip(cs, f))]
fn new_witness<T: Borrow<V>>(
cs: impl Into<Namespace<F>>,
f: impl FnOnce() -> Result<T, SynthesisError>,
) -> Result<Self, SynthesisError> {
Self::new_variable(cs, f, AllocationMode::Witness)
}
}
impl<I, F: Field, A: AllocVar<I, F>> AllocVar<[I], F> for Vec<A> {
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();
let mut vec = Vec::new();
for value in f()?.borrow().iter() {
vec.push(A::new_variable(cs.clone(), || Ok(value), mode)?);
}
Ok(vec)
}
}