Skip to main content

nova_snark/frontend/
shape_cs.rs

1//! Support for generating R1CS shape using bellpepper.
2
3use crate::{
4  frontend::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable},
5  traits::Engine,
6};
7use ff::PrimeField;
8
9/// `ShapeCS` is a `ConstraintSystem` for creating `R1CSShape`s for a circuit.
10pub struct ShapeCS<E: Engine>
11where
12  E::Scalar: PrimeField,
13{
14  /// All constraints added to the `ShapeCS`.
15  pub constraints: Vec<(
16    LinearCombination<E::Scalar>,
17    LinearCombination<E::Scalar>,
18    LinearCombination<E::Scalar>,
19  )>,
20  inputs: usize,
21  aux: usize,
22}
23
24impl<E: Engine> ShapeCS<E> {
25  /// Create a new, default `ShapeCS`,
26  pub fn new() -> Self {
27    ShapeCS::default()
28  }
29
30  /// Returns the number of constraints defined for this `ShapeCS`.
31  pub fn num_constraints(&self) -> usize {
32    self.constraints.len()
33  }
34
35  /// Returns the number of inputs defined for this `ShapeCS`.
36  pub fn num_inputs(&self) -> usize {
37    self.inputs
38  }
39
40  /// Returns the number of aux inputs defined for this `ShapeCS`.
41  pub fn num_aux(&self) -> usize {
42    self.aux
43  }
44}
45
46impl<E: Engine> Default for ShapeCS<E> {
47  fn default() -> Self {
48    ShapeCS {
49      constraints: vec![],
50      inputs: 1,
51      aux: 0,
52    }
53  }
54}
55
56impl<E: Engine> ConstraintSystem<E::Scalar> for ShapeCS<E> {
57  type Root = Self;
58
59  fn alloc<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError>
60  where
61    F: FnOnce() -> Result<E::Scalar, SynthesisError>,
62    A: FnOnce() -> AR,
63    AR: Into<String>,
64  {
65    self.aux += 1;
66
67    Ok(Variable::new_unchecked(Index::Aux(self.aux - 1)))
68  }
69
70  fn alloc_input<F, A, AR>(&mut self, _annotation: A, _f: F) -> Result<Variable, SynthesisError>
71  where
72    F: FnOnce() -> Result<E::Scalar, SynthesisError>,
73    A: FnOnce() -> AR,
74    AR: Into<String>,
75  {
76    self.inputs += 1;
77
78    Ok(Variable::new_unchecked(Index::Input(self.inputs - 1)))
79  }
80
81  fn enforce<A, AR, LA, LB, LC>(&mut self, _annotation: A, a: LA, b: LB, c: LC)
82  where
83    A: FnOnce() -> AR,
84    AR: Into<String>,
85    LA: FnOnce(LinearCombination<E::Scalar>) -> LinearCombination<E::Scalar>,
86    LB: FnOnce(LinearCombination<E::Scalar>) -> LinearCombination<E::Scalar>,
87    LC: FnOnce(LinearCombination<E::Scalar>) -> LinearCombination<E::Scalar>,
88  {
89    let a = a(LinearCombination::zero());
90    let b = b(LinearCombination::zero());
91    let c = c(LinearCombination::zero());
92
93    self.constraints.push((a, b, c));
94  }
95
96  fn push_namespace<NR, N>(&mut self, _name_fn: N)
97  where
98    NR: Into<String>,
99    N: FnOnce() -> NR,
100  {
101  }
102
103  fn pop_namespace(&mut self) {}
104
105  fn get_root(&mut self) -> &mut Self::Root {
106    self
107  }
108}