|  |  | @ -1,41 +1,41 @@ | 
			
		
	
		
			
				
					|  |  |  | #![allow(clippy::type_complexity)]
 | 
			
		
	
		
			
				
					|  |  |  | use super::commitments::Scalar;
 | 
			
		
	
		
			
				
					|  |  |  | use super::commitments::{CommitGens, CommitTrait, Commitment, CompressedCommitment};
 | 
			
		
	
		
			
				
					|  |  |  | use super::commitments::{CommitGens, CommitTrait, Commitment};
 | 
			
		
	
		
			
				
					|  |  |  | use super::errors::NovaError;
 | 
			
		
	
		
			
				
					|  |  |  | use super::traits::{Group, PrimeField};
 | 
			
		
	
		
			
				
					|  |  |  | use itertools::concat;
 | 
			
		
	
		
			
				
					|  |  |  | use rayon::prelude::*;
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSGens {
 | 
			
		
	
		
			
				
					|  |  |  |   gens_W: CommitGens,
 | 
			
		
	
		
			
				
					|  |  |  |   gens_E: CommitGens,
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSGens<G: Group> {
 | 
			
		
	
		
			
				
					|  |  |  |   gens_W: CommitGens<G>,
 | 
			
		
	
		
			
				
					|  |  |  |   gens_E: CommitGens<G>,
 | 
			
		
	
		
			
				
					|  |  |  | }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | #[derive(Debug)]
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSShape {
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSShape<G: Group> {
 | 
			
		
	
		
			
				
					|  |  |  |   num_cons: usize,
 | 
			
		
	
		
			
				
					|  |  |  |   num_vars: usize,
 | 
			
		
	
		
			
				
					|  |  |  |   num_inputs: usize,
 | 
			
		
	
		
			
				
					|  |  |  |   A: Vec<(usize, usize, Scalar)>,
 | 
			
		
	
		
			
				
					|  |  |  |   B: Vec<(usize, usize, Scalar)>,
 | 
			
		
	
		
			
				
					|  |  |  |   C: Vec<(usize, usize, Scalar)>,
 | 
			
		
	
		
			
				
					|  |  |  |   A: Vec<(usize, usize, G::Scalar)>,
 | 
			
		
	
		
			
				
					|  |  |  |   B: Vec<(usize, usize, G::Scalar)>,
 | 
			
		
	
		
			
				
					|  |  |  |   C: Vec<(usize, usize, G::Scalar)>,
 | 
			
		
	
		
			
				
					|  |  |  | }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | #[derive(Clone, Debug)]
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSWitness {
 | 
			
		
	
		
			
				
					|  |  |  |   W: Vec<Scalar>,
 | 
			
		
	
		
			
				
					|  |  |  |   E: Vec<Scalar>,
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSWitness<G: Group> {
 | 
			
		
	
		
			
				
					|  |  |  |   W: Vec<G::Scalar>,
 | 
			
		
	
		
			
				
					|  |  |  |   E: Vec<G::Scalar>,
 | 
			
		
	
		
			
				
					|  |  |  | }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | #[derive(Clone, Debug, PartialEq, Eq)]
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSInstance {
 | 
			
		
	
		
			
				
					|  |  |  |   comm_W: Commitment,
 | 
			
		
	
		
			
				
					|  |  |  |   comm_E: Commitment,
 | 
			
		
	
		
			
				
					|  |  |  |   X: Vec<Scalar>,
 | 
			
		
	
		
			
				
					|  |  |  |   u: Scalar,
 | 
			
		
	
		
			
				
					|  |  |  | pub struct R1CSInstance<G: Group> {
 | 
			
		
	
		
			
				
					|  |  |  |   comm_W: Commitment<G>,
 | 
			
		
	
		
			
				
					|  |  |  |   comm_E: Commitment<G>,
 | 
			
		
	
		
			
				
					|  |  |  |   X: Vec<G::Scalar>,
 | 
			
		
	
		
			
				
					|  |  |  |   u: G::Scalar,
 | 
			
		
	
		
			
				
					|  |  |  | }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | impl R1CSGens {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn new(num_cons: usize, num_vars: usize) -> R1CSGens {
 | 
			
		
	
		
			
				
					|  |  |  | impl<G: Group> R1CSGens<G> {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn new(num_cons: usize, num_vars: usize) -> R1CSGens<G> {
 | 
			
		
	
		
			
				
					|  |  |  |     // generators to commit to witness vector `W`
 | 
			
		
	
		
			
				
					|  |  |  |     let gens_W = CommitGens::new(b"gens_W", num_vars);
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -46,19 +46,19 @@ impl R1CSGens { | 
			
		
	
		
			
				
					|  |  |  |   }
 | 
			
		
	
		
			
				
					|  |  |  | }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | impl R1CSShape {
 | 
			
		
	
		
			
				
					|  |  |  | impl<G: Group> R1CSShape<G> {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn new(
 | 
			
		
	
		
			
				
					|  |  |  |     num_cons: usize,
 | 
			
		
	
		
			
				
					|  |  |  |     num_vars: usize,
 | 
			
		
	
		
			
				
					|  |  |  |     num_inputs: usize,
 | 
			
		
	
		
			
				
					|  |  |  |     A: &[(usize, usize, Scalar)],
 | 
			
		
	
		
			
				
					|  |  |  |     B: &[(usize, usize, Scalar)],
 | 
			
		
	
		
			
				
					|  |  |  |     C: &[(usize, usize, Scalar)],
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<R1CSShape, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     A: &[(usize, usize, G::Scalar)],
 | 
			
		
	
		
			
				
					|  |  |  |     B: &[(usize, usize, G::Scalar)],
 | 
			
		
	
		
			
				
					|  |  |  |     C: &[(usize, usize, G::Scalar)],
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<R1CSShape<G>, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     let is_valid = |num_cons: usize,
 | 
			
		
	
		
			
				
					|  |  |  |                     num_vars: usize,
 | 
			
		
	
		
			
				
					|  |  |  |                     num_io: usize,
 | 
			
		
	
		
			
				
					|  |  |  |                     M: &[(usize, usize, Scalar)]|
 | 
			
		
	
		
			
				
					|  |  |  |                     M: &[(usize, usize, G::Scalar)]|
 | 
			
		
	
		
			
				
					|  |  |  |      -> Result<(), NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |       let res = (0..num_cons)
 | 
			
		
	
		
			
				
					|  |  |  |         .map(|i| {
 | 
			
		
	
	
		
			
				
					|  |  | @ -100,8 +100,8 @@ impl R1CSShape { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   fn multiply_vec(
 | 
			
		
	
		
			
				
					|  |  |  |     &self,
 | 
			
		
	
		
			
				
					|  |  |  |     z: &[Scalar],
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<(Vec<Scalar>, Vec<Scalar>, Vec<Scalar>), NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     z: &[G::Scalar],
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<(Vec<G::Scalar>, Vec<G::Scalar>, Vec<G::Scalar>), NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     if z.len() != self.num_inputs + self.num_vars + 1 {
 | 
			
		
	
		
			
				
					|  |  |  |       return Err(NovaError::InvalidWitnessLength);
 | 
			
		
	
		
			
				
					|  |  |  |     }
 | 
			
		
	
	
		
			
				
					|  |  | @ -110,13 +110,13 @@ impl R1CSShape { | 
			
		
	
		
			
				
					|  |  |  |     // This does not perform any validation of entries in M (e.g., if entries in `M` reference indexes outside the range of `z`)
 | 
			
		
	
		
			
				
					|  |  |  |     // This is safe since we know that `M` is valid
 | 
			
		
	
		
			
				
					|  |  |  |     let sparse_matrix_vec_product =
 | 
			
		
	
		
			
				
					|  |  |  |       |M: &Vec<(usize, usize, Scalar)>, num_rows: usize, z: &[Scalar]| -> Vec<Scalar> {
 | 
			
		
	
		
			
				
					|  |  |  |       |M: &Vec<(usize, usize, G::Scalar)>, num_rows: usize, z: &[G::Scalar]| -> Vec<G::Scalar> {
 | 
			
		
	
		
			
				
					|  |  |  |         (0..M.len())
 | 
			
		
	
		
			
				
					|  |  |  |           .map(|i| {
 | 
			
		
	
		
			
				
					|  |  |  |             let (row, col, val) = M[i];
 | 
			
		
	
		
			
				
					|  |  |  |             (row, val * z[col])
 | 
			
		
	
		
			
				
					|  |  |  |           })
 | 
			
		
	
		
			
				
					|  |  |  |           .fold(vec![Scalar::zero(); num_rows], |mut Mz, (r, v)| {
 | 
			
		
	
		
			
				
					|  |  |  |           .fold(vec![G::Scalar::zero(); num_rows], |mut Mz, (r, v)| {
 | 
			
		
	
		
			
				
					|  |  |  |             Mz[r] += v;
 | 
			
		
	
		
			
				
					|  |  |  |             Mz
 | 
			
		
	
		
			
				
					|  |  |  |           })
 | 
			
		
	
	
		
			
				
					|  |  | @ -131,9 +131,9 @@ impl R1CSShape { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn is_sat(
 | 
			
		
	
		
			
				
					|  |  |  |     &self,
 | 
			
		
	
		
			
				
					|  |  |  |     gens: &R1CSGens,
 | 
			
		
	
		
			
				
					|  |  |  |     U: &R1CSInstance,
 | 
			
		
	
		
			
				
					|  |  |  |     W: &R1CSWitness,
 | 
			
		
	
		
			
				
					|  |  |  |     gens: &R1CSGens<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     U: &R1CSInstance<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     W: &R1CSWitness<G>,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<(), NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     assert_eq!(W.W.len(), self.num_vars);
 | 
			
		
	
		
			
				
					|  |  |  |     assert_eq!(W.E.len(), self.num_cons);
 | 
			
		
	
	
		
			
				
					|  |  | @ -177,12 +177,12 @@ impl R1CSShape { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn commit_T(
 | 
			
		
	
		
			
				
					|  |  |  |     &self,
 | 
			
		
	
		
			
				
					|  |  |  |     gens: &R1CSGens,
 | 
			
		
	
		
			
				
					|  |  |  |     U1: &R1CSInstance,
 | 
			
		
	
		
			
				
					|  |  |  |     W1: &R1CSWitness,
 | 
			
		
	
		
			
				
					|  |  |  |     U2: &R1CSInstance,
 | 
			
		
	
		
			
				
					|  |  |  |     W2: &R1CSWitness,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<(Vec<Scalar>, CompressedCommitment), NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     gens: &R1CSGens<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     U1: &R1CSInstance<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     W1: &R1CSWitness<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     U2: &R1CSInstance<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     W2: &R1CSWitness<G>,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<(Vec<G::Scalar>, Commitment<G>), NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     let (AZ_1, BZ_1, CZ_1) = {
 | 
			
		
	
		
			
				
					|  |  |  |       let Z1 = concat(vec![W1.W.clone(), vec![U1.u], U1.X.clone()]);
 | 
			
		
	
		
			
				
					|  |  |  |       self.multiply_vec(&Z1)?
 | 
			
		
	
	
		
			
				
					|  |  | @ -195,33 +195,37 @@ impl R1CSShape { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let AZ_1_circ_BZ_2 = (0..AZ_1.len())
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|i| AZ_1[i] * BZ_2[i])
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |     let AZ_2_circ_BZ_1 = (0..AZ_2.len())
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|i| AZ_2[i] * BZ_1[i])
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |     let u_1_cdot_CZ_2 = (0..CZ_2.len())
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|i| U1.u * CZ_2[i])
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |     let u_2_cdot_CZ_1 = (0..CZ_1.len())
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|i| U2.u * CZ_1[i])
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let T = AZ_1_circ_BZ_2
 | 
			
		
	
		
			
				
					|  |  |  |       .par_iter()
 | 
			
		
	
		
			
				
					|  |  |  |       .zip(&AZ_2_circ_BZ_1)
 | 
			
		
	
		
			
				
					|  |  |  |       .zip(&u_1_cdot_CZ_2)
 | 
			
		
	
		
			
				
					|  |  |  |       .zip(&u_2_cdot_CZ_1)
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|(((a, b), c), d)| a + b - c - d)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|(((a, b), c), d)| *a + *b - *c - *d)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     let comm_T = T.commit(&gens.gens_E).compress();
 | 
			
		
	
		
			
				
					|  |  |  |     let comm_T = T.commit(&gens.gens_E);
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     Ok((T, comm_T))
 | 
			
		
	
		
			
				
					|  |  |  |   }
 | 
			
		
	
		
			
				
					|  |  |  | }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | impl R1CSWitness {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn new(S: &R1CSShape, W: &[Scalar], E: &[Scalar]) -> Result<R1CSWitness, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  | impl<G: Group> R1CSWitness<G> {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn new(
 | 
			
		
	
		
			
				
					|  |  |  |     S: &R1CSShape<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     W: &[G::Scalar],
 | 
			
		
	
		
			
				
					|  |  |  |     E: &[G::Scalar],
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<R1CSWitness<G>, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     if S.num_vars != W.len() || S.num_cons != E.len() {
 | 
			
		
	
		
			
				
					|  |  |  |       Err(NovaError::InvalidWitnessLength)
 | 
			
		
	
		
			
				
					|  |  |  |     } else {
 | 
			
		
	
	
		
			
				
					|  |  | @ -232,11 +236,16 @@ impl R1CSWitness { | 
			
		
	
		
			
				
					|  |  |  |     }
 | 
			
		
	
		
			
				
					|  |  |  |   }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn commit(&self, gens: &R1CSGens) -> (Commitment, Commitment) {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn commit(&self, gens: &R1CSGens<G>) -> (Commitment<G>, Commitment<G>) {
 | 
			
		
	
		
			
				
					|  |  |  |     (self.W.commit(&gens.gens_W), self.E.commit(&gens.gens_E))
 | 
			
		
	
		
			
				
					|  |  |  |   }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn fold(&self, W2: &R1CSWitness, T: &[Scalar], r: &Scalar) -> Result<R1CSWitness, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn fold(
 | 
			
		
	
		
			
				
					|  |  |  |     &self,
 | 
			
		
	
		
			
				
					|  |  |  |     W2: &R1CSWitness<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     T: &[G::Scalar],
 | 
			
		
	
		
			
				
					|  |  |  |     r: &G::Scalar,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<R1CSWitness<G>, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     let (W1, E1) = (&self.W, &self.E);
 | 
			
		
	
		
			
				
					|  |  |  |     let (W2, E2) = (&W2.W, &W2.E);
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -247,26 +256,26 @@ impl R1CSWitness { | 
			
		
	
		
			
				
					|  |  |  |     let W = W1
 | 
			
		
	
		
			
				
					|  |  |  |       .par_iter()
 | 
			
		
	
		
			
				
					|  |  |  |       .zip(W2)
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|(a, b)| a + r * b)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|(a, b)| *a + *r * *b)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |     let E = E1
 | 
			
		
	
		
			
				
					|  |  |  |       .par_iter()
 | 
			
		
	
		
			
				
					|  |  |  |       .zip(T)
 | 
			
		
	
		
			
				
					|  |  |  |       .zip(E2)
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|((a, b), c)| a + r * b + r * r * c)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|((a, b), c)| *a + *r * *b + *r * *r * *c)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |     Ok(R1CSWitness { W, E })
 | 
			
		
	
		
			
				
					|  |  |  |   }
 | 
			
		
	
		
			
				
					|  |  |  | }
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | impl R1CSInstance {
 | 
			
		
	
		
			
				
					|  |  |  | impl<G: Group> R1CSInstance<G> {
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn new(
 | 
			
		
	
		
			
				
					|  |  |  |     S: &R1CSShape,
 | 
			
		
	
		
			
				
					|  |  |  |     comm_W: &Commitment,
 | 
			
		
	
		
			
				
					|  |  |  |     comm_E: &Commitment,
 | 
			
		
	
		
			
				
					|  |  |  |     X: &[Scalar],
 | 
			
		
	
		
			
				
					|  |  |  |     u: &Scalar,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<R1CSInstance, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     S: &R1CSShape<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     comm_W: &Commitment<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     comm_E: &Commitment<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     X: &[G::Scalar],
 | 
			
		
	
		
			
				
					|  |  |  |     u: &G::Scalar,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<R1CSInstance<G>, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     if S.num_inputs != X.len() {
 | 
			
		
	
		
			
				
					|  |  |  |       Err(NovaError::InvalidInputLength)
 | 
			
		
	
		
			
				
					|  |  |  |     } else {
 | 
			
		
	
	
		
			
				
					|  |  | @ -281,11 +290,10 @@ impl R1CSInstance { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   pub fn fold(
 | 
			
		
	
		
			
				
					|  |  |  |     &self,
 | 
			
		
	
		
			
				
					|  |  |  |     U2: &R1CSInstance,
 | 
			
		
	
		
			
				
					|  |  |  |     comm_T: &CompressedCommitment,
 | 
			
		
	
		
			
				
					|  |  |  |     r: &Scalar,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> Result<R1CSInstance, NovaError> {
 | 
			
		
	
		
			
				
					|  |  |  |     let comm_T_unwrapped = comm_T.decompress()?;
 | 
			
		
	
		
			
				
					|  |  |  |     U2: &R1CSInstance<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     comm_T: &Commitment<G>,
 | 
			
		
	
		
			
				
					|  |  |  |     r: &G::Scalar,
 | 
			
		
	
		
			
				
					|  |  |  |   ) -> R1CSInstance<G> {
 | 
			
		
	
		
			
				
					|  |  |  |     let (X1, u1, comm_W_1, comm_E_1) =
 | 
			
		
	
		
			
				
					|  |  |  |       (&self.X, &self.u, &self.comm_W.clone(), &self.comm_E.clone());
 | 
			
		
	
		
			
				
					|  |  |  |     let (X2, u2, comm_W_2, comm_E_2) = (&U2.X, &U2.u, &U2.comm_W, &U2.comm_E);
 | 
			
		
	
	
		
			
				
					|  |  | @ -294,17 +302,17 @@ impl R1CSInstance { | 
			
		
	
		
			
				
					|  |  |  |     let X = X1
 | 
			
		
	
		
			
				
					|  |  |  |       .par_iter()
 | 
			
		
	
		
			
				
					|  |  |  |       .zip(X2)
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|(a, b)| a + r * b)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |     let comm_W = comm_W_1 + r * comm_W_2;
 | 
			
		
	
		
			
				
					|  |  |  |     let comm_E = comm_E_1 + r * comm_T_unwrapped + r * r * comm_E_2;
 | 
			
		
	
		
			
				
					|  |  |  |     let u = u1 + r * u2;
 | 
			
		
	
		
			
				
					|  |  |  |       .map(|(a, b)| *a + *r * *b)
 | 
			
		
	
		
			
				
					|  |  |  |       .collect::<Vec<G::Scalar>>();
 | 
			
		
	
		
			
				
					|  |  |  |     let comm_W = comm_W_1 + *comm_W_2 * *r;
 | 
			
		
	
		
			
				
					|  |  |  |     let comm_E = *comm_E_1 + *comm_T * *r + *comm_E_2 * *r * *r;
 | 
			
		
	
		
			
				
					|  |  |  |     let u = *u1 + *r * *u2;
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     Ok(R1CSInstance {
 | 
			
		
	
		
			
				
					|  |  |  |     R1CSInstance {
 | 
			
		
	
		
			
				
					|  |  |  |       comm_W,
 | 
			
		
	
		
			
				
					|  |  |  |       comm_E,
 | 
			
		
	
		
			
				
					|  |  |  |       X,
 | 
			
		
	
		
			
				
					|  |  |  |       u,
 | 
			
		
	
		
			
				
					|  |  |  |     })
 | 
			
		
	
		
			
				
					|  |  |  |     }
 | 
			
		
	
		
			
				
					|  |  |  |   }
 | 
			
		
	
		
			
				
					|  |  |  | }
 |