From a6c44c1ee630a191e65f434c1a2dcb7b1032bed5 Mon Sep 17 00:00:00 2001 From: Hanting Zhang Date: Tue, 5 Dec 2023 13:10:36 -0500 Subject: [PATCH] preallocate witness cs (#143) --- src/bellpepper/r1cs.rs | 11 ++++++----- src/lib.rs | 14 ++++++++++---- src/nifs.rs | 4 ++-- src/r1cs/mod.rs | 34 +++++++++++++++++----------------- src/spartan/direct.rs | 2 +- 5 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/bellpepper/r1cs.rs b/src/bellpepper/r1cs.rs index 278390bd..eb1343a7 100644 --- a/src/bellpepper/r1cs.rs +++ b/src/bellpepper/r1cs.rs @@ -16,7 +16,7 @@ use ff::PrimeField; pub trait NovaWitness { /// Return an instance and witness, given a shape and ck. fn r1cs_instance_and_witness( - &self, + self, shape: &R1CSShape, ck: &CommitmentKey, ) -> Result<(R1CSInstance, R1CSWitness), NovaError>; @@ -32,16 +32,17 @@ pub trait NovaShape { impl NovaWitness for SatisfyingAssignment { fn r1cs_instance_and_witness( - &self, + self, shape: &R1CSShape, ck: &CommitmentKey, ) -> Result<(R1CSInstance, R1CSWitness), NovaError> { - let W = R1CSWitness::::new(shape, self.aux_assignment())?; - let X = &self.input_assignment()[1..]; + let (input_assignment, aux_assignment) = self.to_assignments(); + let W = R1CSWitness::::new(shape, aux_assignment)?; + let X = input_assignment[1..].to_owned(); let comm_W = W.commit(ck); - let instance = R1CSInstance::::new(shape, &comm_W, X)?; + let instance = R1CSInstance::::new(shape, comm_W, X)?; Ok((instance, W)) } diff --git a/src/lib.rs b/src/lib.rs index baa09b82..da796894 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -324,9 +324,9 @@ where // IVC proof for the primary circuit let l_w_primary = w_primary; let l_u_primary = u_primary; - let r_W_primary = RelaxedR1CSWitness::from_r1cs_witness(&pp.r1cs_shape_primary, &l_w_primary); + let r_W_primary = RelaxedR1CSWitness::from_r1cs_witness(&pp.r1cs_shape_primary, l_w_primary); let r_U_primary = - RelaxedR1CSInstance::from_r1cs_instance(&pp.ck_primary, &pp.r1cs_shape_primary, &l_u_primary); + RelaxedR1CSInstance::from_r1cs_instance(&pp.ck_primary, &pp.r1cs_shape_primary, l_u_primary); // IVC proof for the secondary circuit let l_w_secondary = w_secondary; @@ -395,7 +395,10 @@ where ) .expect("Unable to fold secondary"); - let mut cs_primary = SatisfyingAssignment::::new(); + let mut cs_primary = SatisfyingAssignment::::with_capacity( + pp.r1cs_shape_primary.num_io + 1, + pp.r1cs_shape_primary.num_vars, + ); let inputs_primary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( scalar_as_base::(pp.digest()), E1::Scalar::from(self.i as u64), @@ -434,7 +437,10 @@ where ) .expect("Unable to fold primary"); - let mut cs_secondary = SatisfyingAssignment::::new(); + let mut cs_secondary = SatisfyingAssignment::::with_capacity( + pp.r1cs_shape_secondary.num_io + 1, + pp.r1cs_shape_secondary.num_vars, + ); let inputs_secondary: NovaAugmentedCircuitInputs = NovaAugmentedCircuitInputs::new( pp.digest(), E2::Scalar::from(self.i as u64), diff --git a/src/nifs.rs b/src/nifs.rs index 881bfd12..878ae05f 100644 --- a/src/nifs.rs +++ b/src/nifs.rs @@ -345,13 +345,13 @@ mod tests { }; let W = { - let res = R1CSWitness::new(&S, &vars); + let res = R1CSWitness::new(&S, vars); assert!(res.is_ok()); res.unwrap() }; let U = { let comm_W = W.commit(ck); - let res = R1CSInstance::new(&S, &comm_W, &X); + let res = R1CSInstance::new(&S, comm_W, X); assert!(res.is_ok()); res.unwrap() }; diff --git a/src/r1cs/mod.rs b/src/r1cs/mod.rs index 84144ef0..f34bd133 100644 --- a/src/r1cs/mod.rs +++ b/src/r1cs/mod.rs @@ -381,11 +381,11 @@ impl R1CSShape { impl R1CSWitness { /// A method to create a witness object using a vector of scalars - pub fn new(S: &R1CSShape, W: &[E::Scalar]) -> Result, NovaError> { + pub fn new(S: &R1CSShape, W: Vec) -> Result, NovaError> { if S.num_vars != W.len() { Err(NovaError::InvalidWitnessLength) } else { - Ok(R1CSWitness { W: W.to_owned() }) + Ok(R1CSWitness { W }) } } @@ -399,16 +399,13 @@ impl R1CSInstance { /// A method to create an instance object using constituent elements pub fn new( S: &R1CSShape, - comm_W: &Commitment, - X: &[E::Scalar], + comm_W: Commitment, + X: Vec, ) -> Result, NovaError> { if S.num_io != X.len() { Err(NovaError::InvalidInputLength) } else { - Ok(R1CSInstance { - comm_W: *comm_W, - X: X.to_owned(), - }) + Ok(R1CSInstance { comm_W, X }) } } } @@ -432,9 +429,9 @@ impl RelaxedR1CSWitness { } /// Initializes a new `RelaxedR1CSWitness` from an `R1CSWitness` - pub fn from_r1cs_witness(S: &R1CSShape, witness: &R1CSWitness) -> RelaxedR1CSWitness { + pub fn from_r1cs_witness(S: &R1CSShape, witness: R1CSWitness) -> RelaxedR1CSWitness { RelaxedR1CSWitness { - W: witness.W.clone(), + W: witness.W, E: vec![E::Scalar::ZERO; S.num_cons], } } @@ -497,15 +494,18 @@ impl RelaxedR1CSInstance { /// Initializes a new `RelaxedR1CSInstance` from an `R1CSInstance` pub fn from_r1cs_instance( - ck: &CommitmentKey, + _ck: &CommitmentKey, S: &R1CSShape, - instance: &R1CSInstance, + instance: R1CSInstance, ) -> RelaxedR1CSInstance { - let mut r_instance = RelaxedR1CSInstance::default(ck, S); - r_instance.comm_W = instance.comm_W; - r_instance.u = E::Scalar::ONE; - r_instance.X = instance.X.clone(); - r_instance + assert_eq!(S.num_io, instance.X.len()); + + RelaxedR1CSInstance { + comm_W: instance.comm_W, + comm_E: Commitment::::default(), + u: E::Scalar::ONE, + X: instance.X, + } } /// Initializes a new `RelaxedR1CSInstance` from an `R1CSInstance` diff --git a/src/spartan/direct.rs b/src/spartan/direct.rs index 046a5c4d..4dbbf6f1 100644 --- a/src/spartan/direct.rs +++ b/src/spartan/direct.rs @@ -137,7 +137,7 @@ impl, C: StepCircuit> DirectSN // convert the instance and witness to relaxed form let (u_relaxed, w_relaxed) = ( RelaxedR1CSInstance::from_r1cs_instance_unchecked(&u.comm_W, &u.X), - RelaxedR1CSWitness::from_r1cs_witness(&pk.S, &w), + RelaxedR1CSWitness::from_r1cs_witness(&pk.S, w), ); // prove the instance using Spartan