arnaucube
arnaucube/NovaPublic Self-hosted repository
Nova/src/bellperson/r1cs.rs
src/bellperson/r1cs.rsRaw
  1//! Support for generating R1CS using bellperson.
  2
  3#![allow(non_snake_case)]
  4
  5use super::{shape_cs::ShapeCS, solver::SatisfyingAssignment};
  6use bellperson::{Index, LinearCombination};
  7
  8use ff::PrimeField;
  9
 10use crate::{
 11  errors::NovaError,
 12  r1cs::{R1CSGens, R1CSInstance, R1CSShape, R1CSWitness},
 13  traits::Group,
 14};
 15
 16/// `NovaWitness` provide a method for acquiring an `R1CSInstance` and `R1CSWitness` from implementers.
 17pub trait NovaWitness<G: Group> {
 18  /// Return an instance and witness, given a shape and gens.
 19  fn r1cs_instance_and_witness(
 20    &self,
 21    shape: &R1CSShape<G>,
 22    gens: &R1CSGens<G>,
 23  ) -> Result<(R1CSInstance<G>, R1CSWitness<G>), NovaError>;
 24}
 25
 26/// `NovaShape` provides methods for acquiring `R1CSShape` and `R1CSGens` from implementers.
 27pub trait NovaShape<G: Group> {
 28  /// Return an appropriate `R1CSShape` struct.
 29  fn r1cs_shape(&self) -> R1CSShape<G>;
 30  /// Return an appropriate `R1CSGens` struct.
 31  fn r1cs_gens(&self) -> R1CSGens<G>;
 32}
 33
 34impl<G: Group> NovaWitness<G> for SatisfyingAssignment<G>
 35where
 36  G::Scalar: PrimeField,
 37{
 38  fn r1cs_instance_and_witness(
 39    &self,
 40    shape: &R1CSShape<G>,
 41    gens: &R1CSGens<G>,
 42  ) -> Result<(R1CSInstance<G>, R1CSWitness<G>), NovaError> {
 43    let W = R1CSWitness::<G>::new(shape, &self.aux_assignment)?;
 44    let X = &self.input_assignment[1..];
 45
 46    let comm_W = W.commit(gens);
 47
 48    let instance = R1CSInstance::<G>::new(shape, &comm_W, X)?;
 49
 50    Ok((instance, W))
 51  }
 52}
 53
 54impl<G: Group> NovaShape<G> for ShapeCS<G>
 55where
 56  G::Scalar: PrimeField,
 57{
 58  fn r1cs_shape(&self) -> R1CSShape<G> {
 59    let mut A: Vec<(usize, usize, G::Scalar)> = Vec::new();
 60    let mut B: Vec<(usize, usize, G::Scalar)> = Vec::new();
 61    let mut C: Vec<(usize, usize, G::Scalar)> = Vec::new();
 62
 63    let mut num_cons_added = 0;
 64    let mut X = (&mut A, &mut B, &mut C, &mut num_cons_added);
 65
 66    let num_inputs = self.num_inputs();
 67    let num_constraints = self.num_constraints();
 68    let num_vars = self.num_aux();
 69
 70    for constraint in self.constraints.iter() {
 71      add_constraint(
 72        &mut X,
 73        num_vars,
 74        &constraint.0,
 75        &constraint.1,
 76        &constraint.2,
 77      );
 78    }
 79
 80    assert_eq!(num_cons_added, num_constraints);
 81
 82    let S: R1CSShape<G> = {
 83      // Don't count One as an input for shape's purposes.
 84      let res = R1CSShape::new(num_constraints, num_vars, num_inputs - 1, &A, &B, &C);
 85      res.unwrap()
 86    };
 87
 88    S
 89  }
 90
 91  fn r1cs_gens(&self) -> R1CSGens<G> {
 92    R1CSGens::<G>::new(self.num_constraints(), self.num_aux())
 93  }
 94}
 95
 96fn add_constraint<S: PrimeField>(
 97  X: &mut (
 98    &mut Vec<(usize, usize, S)>,
 99    &mut Vec<(usize, usize, S)>,
100    &mut Vec<(usize, usize, S)>,
101    &mut usize,
102  ),
103  num_vars: usize,
104  a_lc: &LinearCombination<S>,
105  b_lc: &LinearCombination<S>,
106  c_lc: &LinearCombination<S>,
107) {
108  let (A, B, C, nn) = X;
109  let n = **nn;
110  let one = S::one();
111
112  let add_constraint_component = |index: Index, coeff, V: &mut Vec<_>| {
113    match index {
114      Index::Input(idx) => {
115        // Inputs come last, with input 0, reprsenting 'one',
116        // at position num_vars within the witness vector.
117        let i = idx + num_vars;
118        V.push((n, i, one * coeff))
119      }
120      Index::Aux(idx) => V.push((n, idx, one * coeff)),
121    }
122  };
123
124  for (index, coeff) in a_lc.iter() {
125    add_constraint_component(index.0, coeff, A);
126  }
127  for (index, coeff) in b_lc.iter() {
128    add_constraint_component(index.0, coeff, B)
129  }
130  for (index, coeff) in c_lc.iter() {
131    add_constraint_component(index.0, coeff, C)
132  }
133
134  **nn += 1;
135}