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