diff --git a/src/lib.rs b/src/lib.rs index 8f21d96..c49b3a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ use r1cs::{ R1CSGens, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness, }; use std::marker::PhantomData; -use traits::{AbsorbInROTrait, Group, HashFuncConstantsTrait, HashFuncTrait}; +use traits::{AbsorbInROTrait, Group, HashFuncTrait}; /// A SNARK that holds the proof of a step of an incremental computation pub struct StepSNARK { @@ -28,6 +28,9 @@ pub struct StepSNARK { _p: PhantomData, } +type ROConstants = + <::HashFunc as HashFuncTrait<::Base, ::Scalar>>::Constants; + impl StepSNARK { /// Takes as input a Relaxed R1CS instance-witness tuple `(U1, W1)` and /// an R1CS instance-witness tuple `(U2, W2)` with the same structure `shape` @@ -37,6 +40,7 @@ impl StepSNARK { /// if and only if `W1` satisfies `U1` and `W2` satisfies `U2`. pub fn prove( gens: &R1CSGens, + ro_consts: &ROConstants, S: &R1CSShape, U1: &RelaxedR1CSInstance, W1: &RelaxedR1CSWitness, @@ -50,10 +54,7 @@ impl StepSNARK { NovaError, > { // initialize a new RO - let mut ro = G::HashFunc::new(<::HashFunc as HashFuncTrait< - G::Base, - G::Scalar, - >>::Constants::new()); + let mut ro = G::HashFunc::new(ro_consts.clone()); // append S to the transcript S.absorb_in_ro(&mut ro); @@ -94,15 +95,13 @@ impl StepSNARK { /// if and only if `U1` and `U2` are satisfiable. pub fn verify( &self, + ro_consts: &ROConstants, S: &R1CSShape, U1: &RelaxedR1CSInstance, U2: &R1CSInstance, ) -> Result, NovaError> { // initialize a new RO - let mut ro = G::HashFunc::new(<::HashFunc as HashFuncTrait< - G::Base, - G::Scalar, - >>::Constants::new()); + let mut ro = G::HashFunc::new(ro_consts.clone()); // append S to the transcript S.absorb_in_ro(&mut ro); @@ -152,6 +151,7 @@ impl FinalSNARK { #[cfg(test)] mod tests { use super::*; + use crate::traits::HashFuncConstantsTrait; use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; use ff::{Field, PrimeField}; use rand::rngs::OsRng; @@ -205,6 +205,10 @@ mod tests { let _ = synthesize_tiny_r1cs_bellperson(&mut cs, None); let shape = cs.r1cs_shape(); let gens = cs.r1cs_gens(); + let ro_consts = <::HashFunc as HashFuncTrait< + ::Base, + ::Scalar, + >>::Constants::new(); // Now get the instance and assignment for one instance let mut cs: SatisfyingAssignment = SatisfyingAssignment::new(); @@ -223,11 +227,15 @@ mod tests { assert!(shape.is_sat(&gens, &U2, &W2).is_ok()); // execute a sequence of folds - execute_sequence(&gens, &shape, &U1, &W1, &U2, &W2); + execute_sequence(&gens, &ro_consts, &shape, &U1, &W1, &U2, &W2); } fn execute_sequence( gens: &R1CSGens, + ro_consts: &<::HashFunc as HashFuncTrait< + ::Base, + ::Scalar, + >>::Constants, shape: &R1CSShape, U1: &R1CSInstance, W1: &R1CSWitness, @@ -239,12 +247,12 @@ mod tests { let mut r_U = RelaxedR1CSInstance::default(gens, shape); // produce a step SNARK with (W1, U1) as the first incoming witness-instance pair - let res = StepSNARK::prove(gens, shape, &r_U, &r_W, U1, W1); + let res = StepSNARK::prove(gens, ro_consts, shape, &r_U, &r_W, U1, W1); assert!(res.is_ok()); let (step_snark, (_U, W)) = res.unwrap(); // verify the step SNARK with U1 as the first incoming instance - let res = step_snark.verify(shape, &r_U, U1); + let res = step_snark.verify(ro_consts, shape, &r_U, U1); assert!(res.is_ok()); let U = res.unwrap(); @@ -255,12 +263,12 @@ mod tests { r_U = U; // produce a step SNARK with (W2, U2) as the second incoming witness-instance pair - let res = StepSNARK::prove(gens, shape, &r_U, &r_W, U2, W2); + let res = StepSNARK::prove(gens, ro_consts, shape, &r_U, &r_W, U2, W2); assert!(res.is_ok()); let (step_snark, (_U, W)) = res.unwrap(); // verify the step SNARK with U1 as the first incoming instance - let res = step_snark.verify(shape, &r_U, U2); + let res = step_snark.verify(ro_consts, shape, &r_U, U2); assert!(res.is_ok()); let U = res.unwrap(); @@ -338,8 +346,12 @@ mod tests { res.unwrap() }; - // generate generators + // generate generators and ro constants let gens = R1CSGens::new(num_cons, num_vars); + let ro_consts = <::HashFunc as HashFuncTrait< + ::Base, + ::Scalar, + >>::Constants::new(); let rand_inst_witness_generator = |gens: &R1CSGens, I: &S| -> (S, R1CSInstance, R1CSWitness) { @@ -382,6 +394,6 @@ mod tests { let (_O, U2, W2) = rand_inst_witness_generator(&gens, &O); // execute a sequence of folds - execute_sequence(&gens, &S, &U1, &W1, &U2, &W2); + execute_sequence(&gens, &ro_consts, &S, &U1, &W1, &U2, &W2); } } diff --git a/src/traits.rs b/src/traits.rs index 52adefe..7c7e70e 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -89,7 +89,7 @@ pub trait ChallengeTrait { /// A helper trait that defines the behavior of a hash function that we use as an RO pub trait HashFuncTrait { /// A type representing constants/parameters associated with the hash function - type Constants: HashFuncConstantsTrait; + type Constants: HashFuncConstantsTrait + Clone; /// Initializes the hash function fn new(constants: Self::Constants) -> Self;