snarkvm_algorithms/r1cs/
constraint_system.rs

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