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}