Skip to main content

nova_snark/frontend/util_cs/
witness_cs.rs

1//! Support for efficiently generating R1CS witness using bellperson.
2
3use ff::PrimeField;
4
5use crate::frontend::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable};
6
7/// A [`ConstraintSystem`] trait
8pub trait SizedWitness<Scalar: PrimeField> {
9  /// Returns the number of constraints in the constraint system
10  fn num_constraints(&self) -> usize;
11  /// Returns the number of inputs in the constraint system
12  fn num_inputs(&self) -> usize;
13  /// Returns the number of auxiliary variables in the constraint system
14  fn num_aux(&self) -> usize;
15
16  /// Generate a witness for the constraint system
17  fn generate_witness_into(&mut self, aux: &mut [Scalar], inputs: &mut [Scalar]) -> Scalar;
18
19  /// Generate a witness for the constraint system
20  fn generate_witness_into_cs<CS: ConstraintSystem<Scalar>>(&mut self, cs: &mut CS) -> Scalar {
21    assert!(cs.is_witness_generator());
22
23    let aux_count = self.num_aux();
24    let inputs_count = self.num_inputs();
25
26    let (aux, inputs) = cs.allocate_empty(aux_count, inputs_count);
27
28    assert_eq!(aux.len(), aux_count);
29    assert_eq!(inputs.len(), inputs_count);
30
31    self.generate_witness_into(aux, inputs)
32  }
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
36/// A `ConstraintSystem` which calculates witness values for a concrete instance of an R1CS circuit.
37pub struct WitnessCS<Scalar>
38where
39  Scalar: PrimeField,
40{
41  // Assignments of variables
42  pub(crate) input_assignment: Vec<Scalar>,
43  pub(crate) aux_assignment: Vec<Scalar>,
44}
45
46impl<Scalar> WitnessCS<Scalar>
47where
48  Scalar: PrimeField,
49{
50  /// Get input assignment
51  pub fn input_assignment(&self) -> &[Scalar] {
52    &self.input_assignment
53  }
54
55  /// Get aux assignment
56  pub fn aux_assignment(&self) -> &[Scalar] {
57    &self.aux_assignment
58  }
59}
60
61impl<Scalar> ConstraintSystem<Scalar> for WitnessCS<Scalar>
62where
63  Scalar: PrimeField,
64{
65  type Root = Self;
66
67  fn new() -> Self {
68    let input_assignment = vec![Scalar::ONE];
69
70    Self {
71      input_assignment,
72      aux_assignment: vec![],
73    }
74  }
75
76  fn alloc<F, A, AR>(&mut self, _: A, f: F) -> Result<Variable, SynthesisError>
77  where
78    F: FnOnce() -> Result<Scalar, SynthesisError>,
79    A: FnOnce() -> AR,
80    AR: Into<String>,
81  {
82    self.aux_assignment.push(f()?);
83
84    Ok(Variable(Index::Aux(self.aux_assignment.len() - 1)))
85  }
86
87  fn alloc_input<F, A, AR>(&mut self, _: A, f: F) -> Result<Variable, SynthesisError>
88  where
89    F: FnOnce() -> Result<Scalar, SynthesisError>,
90    A: FnOnce() -> AR,
91    AR: Into<String>,
92  {
93    self.input_assignment.push(f()?);
94
95    Ok(Variable(Index::Input(self.input_assignment.len() - 1)))
96  }
97
98  fn enforce<A, AR, LA, LB, LC>(&mut self, _: A, _a: LA, _b: LB, _c: LC)
99  where
100    A: FnOnce() -> AR,
101    AR: Into<String>,
102    LA: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
103    LB: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
104    LC: FnOnce(LinearCombination<Scalar>) -> LinearCombination<Scalar>,
105  {
106    // Do nothing: we don't care about linear-combination evaluations in this context.
107  }
108
109  fn push_namespace<NR, N>(&mut self, _: N)
110  where
111    NR: Into<String>,
112    N: FnOnce() -> NR,
113  {
114    // Do nothing; we don't care about namespaces in this context.
115  }
116
117  fn pop_namespace(&mut self) {
118    // Do nothing; we don't care about namespaces in this context.
119  }
120
121  fn get_root(&mut self) -> &mut Self::Root {
122    self
123  }
124
125  ////////////////////////////////////////////////////////////////////////////////
126  // Extensible
127  fn is_extensible() -> bool {
128    true
129  }
130
131  fn extend(&mut self, other: &Self) {
132    self.input_assignment
133            // Skip first input, which must have been a temporarily allocated one variable.
134            .extend(&other.input_assignment[1..]);
135    self.aux_assignment.extend(&other.aux_assignment);
136  }
137
138  ////////////////////////////////////////////////////////////////////////////////
139  // Witness generator
140  fn is_witness_generator(&self) -> bool {
141    true
142  }
143
144  fn extend_inputs(&mut self, new_inputs: &[Scalar]) {
145    self.input_assignment.extend(new_inputs);
146  }
147
148  fn extend_aux(&mut self, new_aux: &[Scalar]) {
149    self.aux_assignment.extend(new_aux);
150  }
151
152  fn allocate_empty(&mut self, aux_n: usize, inputs_n: usize) -> (&mut [Scalar], &mut [Scalar]) {
153    let allocated_aux = {
154      let i = self.aux_assignment.len();
155      self.aux_assignment.resize(aux_n + i, Scalar::ZERO);
156      &mut self.aux_assignment[i..]
157    };
158
159    let allocated_inputs = {
160      let i = self.input_assignment.len();
161      self.input_assignment.resize(inputs_n + i, Scalar::ZERO);
162      &mut self.input_assignment[i..]
163    };
164
165    (allocated_aux, allocated_inputs)
166  }
167
168  fn inputs_slice(&self) -> &[Scalar] {
169    &self.input_assignment
170  }
171
172  fn aux_slice(&self) -> &[Scalar] {
173    &self.aux_assignment
174  }
175}