1use std::io;
2use std::marker::PhantomData;
3
4use ff::PrimeField;
5
6use crate::{Index, LinearCombination, Variable};
7
8pub trait Circuit<Scalar: PrimeField> {
13 fn synthesize<CS: ConstraintSystem<Scalar>>(self, cs: &mut CS) -> Result<(), SynthesisError>;
15}
16
17#[allow(clippy::upper_case_acronyms)]
20#[derive(thiserror::Error, Debug)]
21pub enum SynthesisError {
22 #[error("an assignment for a variable could not be computed")]
24 AssignmentMissing,
25 #[error("division by zero")]
27 DivisionByZero,
28 #[error("unsatisfiable constraint system")]
30 Unsatisfiable,
31 #[error("polynomial degree is too large")]
33 PolynomialDegreeTooLarge,
34 #[error("encountered an identity element in the CRS")]
36 UnexpectedIdentity,
37 #[error("encountered an I/O error: {0}")]
39 IoError(#[from] io::Error),
40 #[error("malformed verifying key")]
42 MalformedVerifyingKey,
43 #[error("auxiliary variable was unconstrained")]
45 UnconstrainedVariable,
46 #[error("attempted to aggregate malformed proofs: {0}")]
48 MalformedProofs(String),
49 #[error("malformed SRS")]
50 MalformedSrs,
51 #[error("non power of two proofs given for aggregation")]
52 NonPowerOfTwo,
53 #[error("incompatible vector length: {0}")]
54 IncompatibleLengthVector(String),
55 #[error("invalid pairing")]
56 InvalidPairing,
57}
58
59pub trait ConstraintSystem<Scalar: PrimeField>: Sized + Send {
62 type Root: ConstraintSystem<Scalar>;
65
66 fn new() -> Self {
67 unimplemented!(
68 "ConstraintSystem::new must be implemented for extensible types implementing ConstraintSystem"
69 );
70 }
71
72 fn one() -> Variable {
74 Variable::new_unchecked(Index::Input(0))
75 }
76
77 fn alloc<F, A, AR>(&mut self, annotation: A, f: F) -> Result<Variable, SynthesisError>
82 where
83 F: FnOnce() -> Result<Scalar, SynthesisError>,
84 A: FnOnce() -> AR,
85 AR: Into<String>;
86
87 fn alloc_input<F, A, AR>(&mut self, annotation: A, f: F) -> Result<Variable, SynthesisError>
90 where
91 F: FnOnce() -> Result<Scalar, SynthesisError>,
92 A: FnOnce() -> AR,
93 AR: Into<String>;
94
95 fn enforce<A, AR, LA, LB, LC>(&mut self, annotation: A, a: LA, b: LB, c: LC)
98 where
99 A: FnOnce() -> AR,
100 AR: Into<String>,
101 LA: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
102 LB: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
103 LC: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>;
104
105 fn push_namespace<NR, N>(&mut self, name_fn: N)
108 where
109 NR: Into<String>,
110 N: FnOnce() -> NR;
111
112 fn pop_namespace(&mut self);
115
116 fn get_root(&mut self) -> &mut Self::Root;
119
120 fn namespace<NR, N>(&mut self, name_fn: N) -> Namespace<'_, Scalar, Self::Root>
122 where
123 NR: Into<String>,
124 N: FnOnce() -> NR,
125 {
126 self.get_root().push_namespace(name_fn);
127
128 Namespace(self.get_root(), Default::default())
129 }
130
131 fn is_extensible() -> bool {
135 false
136 }
137
138 fn extend(&mut self, _other: &Self) {
145 unimplemented!(
146 "ConstraintSystem::extend must be implemented for types implementing ConstraintSystem"
147 );
148 }
149
150 fn is_witness_generator(&self) -> bool {
158 false
159 }
160
161 fn extend_inputs(&mut self, _new_inputs: &[Scalar]) {
167 assert!(self.is_witness_generator());
168 unimplemented!("ConstraintSystem::extend_inputs must be implemented for witness generators implementing ConstraintSystem")
169 }
170
171 fn extend_aux(&mut self, _new_aux: &[Scalar]) {
177 assert!(self.is_witness_generator());
178 unimplemented!("ConstraintSystem::extend_aux must be implemented for witness generators implementing ConstraintSystem")
179 }
180
181 fn allocate_empty(
187 &mut self,
188 _aux_n: usize,
189 _inputs_n: usize,
190 ) -> (&mut [Scalar], &mut [Scalar]) {
191 assert!(self.is_witness_generator());
193 unimplemented!("ConstraintSystem::allocate_empty must be implemented for witness generators implementing ConstraintSystem")
194 }
195
196 fn allocate_empty_inputs(&mut self, _n: usize) -> &mut [Scalar] {
202 assert!(self.is_witness_generator());
204 unimplemented!("ConstraintSystem::allocate_empty_inputs must be implemented for witness generators implementing ConstraintSystem")
205 }
206
207 fn allocate_empty_aux(&mut self, _n: usize) -> &mut [Scalar] {
213 assert!(self.is_witness_generator());
215 unimplemented!("ConstraintSystem::allocate_empty_aux must be implemented for witness generators implementing ConstraintSystem")
216 }
217
218 fn inputs_slice(&self) -> &[Scalar] {
224 assert!(self.is_witness_generator());
225 unimplemented!("ConstraintSystem::inputs_slice must be implemented for witness generators implementing ConstraintSystem")
226 }
227
228 fn aux_slice(&self) -> &[Scalar] {
234 assert!(self.is_witness_generator());
235 unimplemented!("ConstraintSystem::aux_slice must be implemented for witness generators implementing ConstraintSystem")
236 }
237}
238
239#[derive(Debug)]
242pub struct Namespace<'a, Scalar: PrimeField, CS: ConstraintSystem<Scalar>>(
243 &'a mut CS,
244 PhantomData<Scalar>,
245);
246
247impl<'cs, Scalar: PrimeField, CS: ConstraintSystem<Scalar>> ConstraintSystem<Scalar>
248 for Namespace<'cs, Scalar, CS>
249{
250 type Root = CS::Root;
251
252 fn one() -> Variable {
253 CS::one()
254 }
255
256 fn alloc<F, A, AR>(&mut self, annotation: A, f: F) -> Result<Variable, SynthesisError>
257 where
258 F: FnOnce() -> Result<Scalar, SynthesisError>,
259 A: FnOnce() -> AR,
260 AR: Into<String>,
261 {
262 self.0.alloc(annotation, f)
263 }
264
265 fn alloc_input<F, A, AR>(&mut self, annotation: A, f: F) -> Result<Variable, SynthesisError>
266 where
267 F: FnOnce() -> Result<Scalar, SynthesisError>,
268 A: FnOnce() -> AR,
269 AR: Into<String>,
270 {
271 self.0.alloc_input(annotation, f)
272 }
273
274 fn enforce<A, AR, LA, LB, LC>(&mut self, annotation: A, a: LA, b: LB, c: LC)
275 where
276 A: FnOnce() -> AR,
277 AR: Into<String>,
278 LA: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
279 LB: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
280 LC: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
281 {
282 self.0.enforce(annotation, a, b, c)
283 }
284
285 fn push_namespace<NR, N>(&mut self, _: N)
290 where
291 NR: Into<String>,
292 N: FnOnce() -> NR,
293 {
294 panic!("only the root's push_namespace should be called");
295 }
296
297 fn pop_namespace(&mut self) {
298 panic!("only the root's pop_namespace should be called");
299 }
300
301 fn get_root(&mut self) -> &mut Self::Root {
302 self.0.get_root()
303 }
304
305 fn is_witness_generator(&self) -> bool {
306 self.0.is_witness_generator()
307 }
308
309 fn extend_inputs(&mut self, new_inputs: &[Scalar]) {
310 self.0.extend_inputs(new_inputs)
311 }
312
313 fn extend_aux(&mut self, new_aux: &[Scalar]) {
314 self.0.extend_aux(new_aux)
315 }
316
317 fn allocate_empty(&mut self, aux_n: usize, inputs_n: usize) -> (&mut [Scalar], &mut [Scalar]) {
318 self.0.allocate_empty(aux_n, inputs_n)
319 }
320
321 fn inputs_slice(&self) -> &[Scalar] {
322 self.0.inputs_slice()
323 }
324 fn aux_slice(&self) -> &[Scalar] {
325 self.0.aux_slice()
326 }
327}
328
329impl<'a, Scalar: PrimeField, CS: ConstraintSystem<Scalar>> Drop for Namespace<'a, Scalar, CS> {
330 fn drop(&mut self) {
331 self.get_root().pop_namespace()
332 }
333}
334
335impl<'cs, Scalar: PrimeField, CS: ConstraintSystem<Scalar>> ConstraintSystem<Scalar>
338 for &'cs mut CS
339{
340 type Root = CS::Root;
341
342 fn one() -> Variable {
343 CS::one()
344 }
345
346 fn alloc<F, A, AR>(&mut self, annotation: A, f: F) -> Result<Variable, SynthesisError>
347 where
348 F: FnOnce() -> Result<Scalar, SynthesisError>,
349 A: FnOnce() -> AR,
350 AR: Into<String>,
351 {
352 (**self).alloc(annotation, f)
353 }
354
355 fn alloc_input<F, A, AR>(&mut self, annotation: A, f: F) -> Result<Variable, SynthesisError>
356 where
357 F: FnOnce() -> Result<Scalar, SynthesisError>,
358 A: FnOnce() -> AR,
359 AR: Into<String>,
360 {
361 (**self).alloc_input(annotation, f)
362 }
363
364 fn enforce<A, AR, LA, LB, LC>(&mut self, annotation: A, a: LA, b: LB, c: LC)
365 where
366 A: FnOnce() -> AR,
367 AR: Into<String>,
368 LA: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
369 LB: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
370 LC: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
371 {
372 (**self).enforce(annotation, a, b, c)
373 }
374
375 fn push_namespace<NR, N>(&mut self, name_fn: N)
376 where
377 NR: Into<String>,
378 N: FnOnce() -> NR,
379 {
380 (**self).push_namespace(name_fn)
381 }
382
383 fn pop_namespace(&mut self) {
384 (**self).pop_namespace()
385 }
386
387 fn get_root(&mut self) -> &mut Self::Root {
388 (**self).get_root()
389 }
390
391 fn namespace<NR, N>(&mut self, name_fn: N) -> Namespace<'_, Scalar, Self::Root>
392 where
393 NR: Into<String>,
394 N: FnOnce() -> NR,
395 {
396 (**self).namespace(name_fn)
397 }
398
399 fn is_extensible() -> bool {
400 CS::is_extensible()
401 }
402
403 fn extend(&mut self, other: &Self) {
404 (**self).extend(other)
405 }
406
407 fn is_witness_generator(&self) -> bool {
408 (**self).is_witness_generator()
409 }
410
411 fn extend_inputs(&mut self, new_inputs: &[Scalar]) {
412 (**self).extend_inputs(new_inputs)
413 }
414
415 fn extend_aux(&mut self, new_aux: &[Scalar]) {
416 (**self).extend_aux(new_aux)
417 }
418
419 fn allocate_empty(&mut self, aux_n: usize, inputs_n: usize) -> (&mut [Scalar], &mut [Scalar]) {
420 (**self).allocate_empty(aux_n, inputs_n)
421 }
422
423 fn allocate_empty_inputs(&mut self, n: usize) -> &mut [Scalar] {
424 (**self).allocate_empty_inputs(n)
425 }
426
427 fn allocate_empty_aux(&mut self, n: usize) -> &mut [Scalar] {
428 (**self).allocate_empty_aux(n)
429 }
430
431 fn inputs_slice(&self) -> &[Scalar] {
432 (**self).inputs_slice()
433 }
434
435 fn aux_slice(&self) -> &[Scalar] {
436 (**self).aux_slice()
437 }
438}