snarkvm_r1cs/
constraint_system.rs

1// Copyright (C) 2019-2023 Aleo Systems Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7// http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{errors::SynthesisError, Index, LinearCombination, Namespace, Variable};
16use snarkvm_fields::Field;
17
18use std::marker::PhantomData;
19
20/// Computations are expressed in terms of rank-1 constraint systems (R1CS).
21/// The `generate_constraints` method is called to generate constraints for
22/// both CRS generation and for proving.
23pub trait ConstraintSynthesizer<F: Field>: Sync {
24    /// Drives generation of new constraints inside `CS`.
25    fn generate_constraints<CS: ConstraintSystem<F>>(&self, cs: &mut CS) -> Result<(), SynthesisError>;
26}
27
28/// Represents a constraint system which can have new variables
29/// allocated and constrains between them formed.
30pub trait ConstraintSystem<F: Field>: Sized {
31    /// Represents the type of the "root" of this constraint system
32    /// so that nested namespaces can minimize indirection.
33    type Root: ConstraintSystem<F>;
34
35    /// Return the "one" input variable
36    fn one() -> Variable {
37        Variable::new_unchecked(Index::Public(0))
38    }
39
40    /// Allocate a private variable in the constraint system. The provided
41    /// function is used to determine the assignment of the variable. The
42    /// given `annotation` function is invoked in testing contexts in order
43    /// to derive a unique name for this variable in the current namespace.
44    fn alloc<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
45    where
46        FN: FnOnce() -> Result<F, SynthesisError>,
47        A: FnOnce() -> AR,
48        AR: AsRef<str>;
49
50    /// Allocate a public variable in the constraint system. The provided
51    /// function is used to determine the assignment of the variable.
52    fn alloc_input<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
53    where
54        FN: FnOnce() -> Result<F, SynthesisError>,
55        A: FnOnce() -> AR,
56        AR: AsRef<str>;
57
58    /// Enforce that `A` * `B` = `C`. The `annotation` function is invoked in
59    /// testing contexts in order to derive a unique name for the constraint
60    /// in the current namespace.
61    fn enforce<A, AR, LA, LB, LC>(&mut self, annotation: A, a: LA, b: LB, c: LC)
62    where
63        A: FnOnce() -> AR,
64        AR: AsRef<str>,
65        LA: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
66        LB: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
67        LC: FnOnce(LinearCombination<F>) -> LinearCombination<F>;
68
69    /// Create a new (sub)namespace and enter into it. Not intended
70    /// for downstream use; use `namespace` instead.
71    fn push_namespace<NR, N>(&mut self, name_fn: N)
72    where
73        NR: AsRef<str>,
74        N: FnOnce() -> NR;
75
76    /// Exit out of the existing namespace. Not intended for
77    /// downstream use; use `namespace` instead.
78    fn pop_namespace(&mut self);
79
80    /// Gets the "root" constraint system, bypassing the namespacing.
81    /// Not intended for downstream use; use `namespace` instead.
82    fn get_root(&mut self) -> &mut Self::Root;
83
84    /// Begin a namespace for this constraint system.
85    fn ns<NR, N>(&mut self, name_fn: N) -> Namespace<'_, F, Self::Root>
86    where
87        NR: AsRef<str>,
88        N: FnOnce() -> NR,
89    {
90        self.get_root().push_namespace(name_fn);
91
92        Namespace(self.get_root(), PhantomData)
93    }
94
95    /// Output the number of constraints in the system.
96    fn num_constraints(&self) -> usize;
97
98    /// Output the number of public input variables to the system.
99    fn num_public_variables(&self) -> usize;
100
101    /// Output the number of private input variables to the system.
102    fn num_private_variables(&self) -> usize;
103
104    /// Output whether the constraint system is in the setup mode.
105    fn is_in_setup_mode(&self) -> bool;
106}
107
108/// Convenience implementation of ConstraintSystem<F> for mutable references to
109/// constraint systems.
110impl<F: Field, CS: ConstraintSystem<F>> ConstraintSystem<F> for &mut CS {
111    type Root = CS::Root;
112
113    #[inline]
114    fn one() -> Variable {
115        CS::one()
116    }
117
118    #[inline]
119    fn alloc<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
120    where
121        FN: FnOnce() -> Result<F, SynthesisError>,
122        A: FnOnce() -> AR,
123        AR: AsRef<str>,
124    {
125        (**self).alloc(annotation, f)
126    }
127
128    #[inline]
129    fn alloc_input<FN, A, AR>(&mut self, annotation: A, f: FN) -> Result<Variable, SynthesisError>
130    where
131        FN: FnOnce() -> Result<F, SynthesisError>,
132        A: FnOnce() -> AR,
133        AR: AsRef<str>,
134    {
135        (**self).alloc_input(annotation, f)
136    }
137
138    #[inline]
139    fn enforce<A, AR, LA, LB, LC>(&mut self, annotation: A, a: LA, b: LB, c: LC)
140    where
141        A: FnOnce() -> AR,
142        AR: AsRef<str>,
143        LA: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
144        LB: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
145        LC: FnOnce(LinearCombination<F>) -> LinearCombination<F>,
146    {
147        (**self).enforce(annotation, a, b, c)
148    }
149
150    #[inline]
151    fn push_namespace<NR, N>(&mut self, name_fn: N)
152    where
153        NR: AsRef<str>,
154        N: FnOnce() -> NR,
155    {
156        (**self).push_namespace(name_fn)
157    }
158
159    #[inline]
160    fn pop_namespace(&mut self) {
161        (**self).pop_namespace()
162    }
163
164    #[inline]
165    fn get_root(&mut self) -> &mut Self::Root {
166        (**self).get_root()
167    }
168
169    #[inline]
170    fn num_constraints(&self) -> usize {
171        (**self).num_constraints()
172    }
173
174    #[inline]
175    fn num_public_variables(&self) -> usize {
176        (**self).num_public_variables()
177    }
178
179    #[inline]
180    fn num_private_variables(&self) -> usize {
181        (**self).num_private_variables()
182    }
183
184    #[inline]
185    fn is_in_setup_mode(&self) -> bool {
186        (**self).is_in_setup_mode()
187    }
188}