@ -192,197 +192,207 @@ where
C1 : StepCircuit < G1 ::Scalar > ,
C2 : StepCircuit < G2 ::Scalar > ,
{
/// Create new instance of recursive SNARK
pub fn new (
pp : & PublicParams < G1 , G2 , C1 , C2 > ,
c_primary : & C1 ,
c_secondary : & C2 ,
z0_primary : Vec < G1 ::Scalar > ,
z0_secondary : Vec < G2 ::Scalar > ,
) -> Self {
// Expected outputs of the two circuits
let zi_primary = c_primary . output ( & z0_primary ) ;
let zi_secondary = c_secondary . output ( & z0_secondary ) ;
// base case for the primary
let mut cs_primary : SatisfyingAssignment < G1 > = SatisfyingAssignment ::new ( ) ;
let inputs_primary : NovaAugmentedCircuitInputs < G2 > = NovaAugmentedCircuitInputs ::new (
scalar_as_base ::< G1 > ( pp . digest ) ,
G1 ::Scalar ::ZERO ,
z0_primary ,
None ,
None ,
None ,
None ,
) ;
let circuit_primary : NovaAugmentedCircuit < G2 , C1 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_primary . clone ( ) ,
Some ( inputs_primary ) ,
c_primary . clone ( ) ,
pp . ro_consts_circuit_primary . clone ( ) ,
) ;
let _ = circuit_primary . synthesize ( & mut cs_primary ) ;
let ( u_primary , w_primary ) = cs_primary
. r1cs_instance_and_witness ( & pp . r1cs_shape_primary , & pp . ck_primary )
. map_err ( | _e | NovaError ::UnSat )
. expect ( "Nova error unsat" ) ;
// base case for the secondary
let mut cs_secondary : SatisfyingAssignment < G2 > = SatisfyingAssignment ::new ( ) ;
let inputs_secondary : NovaAugmentedCircuitInputs < G1 > = NovaAugmentedCircuitInputs ::new (
pp . digest ,
G2 ::Scalar ::ZERO ,
z0_secondary ,
None ,
None ,
Some ( u_primary . clone ( ) ) ,
None ,
) ;
let circuit_secondary : NovaAugmentedCircuit < G1 , C2 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_secondary . clone ( ) ,
Some ( inputs_secondary ) ,
c_secondary . clone ( ) ,
pp . ro_consts_circuit_secondary . clone ( ) ,
) ;
let _ = circuit_secondary . synthesize ( & mut cs_secondary ) ;
let ( u_secondary , w_secondary ) = cs_secondary
. r1cs_instance_and_witness ( & pp . r1cs_shape_secondary , & pp . ck_secondary )
. map_err ( | _e | NovaError ::UnSat )
. expect ( "Nova error unsat" ) ;
// 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_U_primary =
RelaxedR1CSInstance ::from_r1cs_instance ( & pp . ck_primary , & pp . r1cs_shape_primary , & l_u_primary ) ;
// IVC proof of the secondary circuit
let l_w_secondary = w_secondary ;
let l_u_secondary = u_secondary ;
let r_W_secondary = RelaxedR1CSWitness ::< G2 > ::default ( & pp . r1cs_shape_secondary ) ;
let r_U_secondary =
RelaxedR1CSInstance ::< G2 > ::default ( & pp . ck_secondary , & pp . r1cs_shape_secondary ) ;
if zi_primary . len ( ) ! = pp . F_arity_primary | | zi_secondary . len ( ) ! = pp . F_arity_secondary {
panic ! ( "Invalid step length" ) ;
}
Self {
r_W_primary ,
r_U_primary ,
r_W_secondary ,
r_U_secondary ,
l_w_secondary ,
l_u_secondary ,
i : 0 ,
zi_primary ,
zi_secondary ,
_p_c1 : Default ::default ( ) ,
_p_c2 : Default ::default ( ) ,
}
}
/// Create a new `RecursiveSNARK` (or updates the provided `RecursiveSNARK`)
/// by executing a step of the incremental computation
pub fn prove_step (
& mut self ,
pp : & PublicParams < G1 , G2 , C1 , C2 > ,
recursive_snark : Option < Self > ,
c_primary : C1 ,
c_secondary : C2 ,
c_primary : & C1 ,
c_secondary : & C2 ,
z0_primary : Vec < G1 ::Scalar > ,
z0_secondary : Vec < G2 ::Scalar > ,
) -> Result < Self , NovaError > {
) -> Result < ( ) , NovaError > {
if z0_primary . len ( ) ! = pp . F_arity_primary | | z0_secondary . len ( ) ! = pp . F_arity_secondary {
return Err ( NovaError ::InvalidInitialInputLength ) ;
}
match recursive_snark {
None = > {
// base case for the primary
let mut cs_primary : SatisfyingAssignment < G1 > = SatisfyingAssignment ::new ( ) ;
let inputs_primary : NovaAugmentedCircuitInputs < G2 > = NovaAugmentedCircuitInputs ::new (
scalar_as_base ::< G1 > ( pp . digest ) ,
G1 ::Scalar ::ZERO ,
z0_primary . clone ( ) ,
None ,
None ,
None ,
None ,
) ;
// Frist step was already done in the constructor
if self . i = = 0 {
self . i = 1 ;
return Ok ( ( ) ) ;
}
let circuit_primary : NovaAugmentedCircuit < G2 , C1 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_primary . clone ( ) ,
Some ( inputs_primary ) ,
c_primary . clone ( ) ,
pp . ro_consts_circuit_primary . clone ( ) ,
) ;
let _ = circuit_primary . synthesize ( & mut cs_primary ) ;
let ( u_primary , w_primary ) = cs_primary
. r1cs_instance_and_witness ( & pp . r1cs_shape_primary , & pp . ck_primary )
. map_err ( | _e | NovaError ::UnSat ) ? ;
// base case for the secondary
let mut cs_secondary : SatisfyingAssignment < G2 > = SatisfyingAssignment ::new ( ) ;
let inputs_secondary : NovaAugmentedCircuitInputs < G1 > = NovaAugmentedCircuitInputs ::new (
pp . digest ,
G2 ::Scalar ::ZERO ,
z0_secondary . clone ( ) ,
None ,
None ,
Some ( u_primary . clone ( ) ) ,
None ,
) ;
let circuit_secondary : NovaAugmentedCircuit < G1 , C2 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_secondary . clone ( ) ,
Some ( inputs_secondary ) ,
c_secondary . clone ( ) ,
pp . ro_consts_circuit_secondary . clone ( ) ,
) ;
let _ = circuit_secondary . synthesize ( & mut cs_secondary ) ;
let ( u_secondary , w_secondary ) = cs_secondary
. r1cs_instance_and_witness ( & pp . r1cs_shape_secondary , & pp . ck_secondary )
. map_err ( | _e | NovaError ::UnSat ) ? ;
// 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_U_primary = RelaxedR1CSInstance ::from_r1cs_instance (
& pp . ck_primary ,
& pp . r1cs_shape_primary ,
& l_u_primary ,
) ;
// fold the secondary circuit's instance
let ( nifs_secondary , ( r_U_secondary , r_W_secondary ) ) = NIFS ::prove (
& pp . ck_secondary ,
& pp . ro_consts_secondary ,
& scalar_as_base ::< G1 > ( pp . digest ) ,
& pp . r1cs_shape_secondary ,
& self . r_U_secondary ,
& self . r_W_secondary ,
& self . l_u_secondary ,
& self . l_w_secondary ,
)
. expect ( "Unable to fold secondary" ) ;
let mut cs_primary : SatisfyingAssignment < G1 > = SatisfyingAssignment ::new ( ) ;
let inputs_primary : NovaAugmentedCircuitInputs < G2 > = NovaAugmentedCircuitInputs ::new (
scalar_as_base ::< G1 > ( pp . digest ) ,
G1 ::Scalar ::from ( self . i as u64 ) ,
z0_primary ,
Some ( self . zi_primary . clone ( ) ) ,
Some ( self . r_U_secondary . clone ( ) ) ,
Some ( self . l_u_secondary . clone ( ) ) ,
Some ( Commitment ::< G2 > ::decompress ( & nifs_secondary . comm_T ) ? ) ,
) ;
// IVC proof of the secondary circuit
let l_w_secondary = w_secondary ;
let l_u_secondary = u_secondary ;
let r_W_secondary = RelaxedR1CSWitness ::< G2 > ::default ( & pp . r1cs_shape_secondary ) ;
let r_U_secondary =
RelaxedR1CSInstance ::< G2 > ::default ( & pp . ck_secondary , & pp . r1cs_shape_secondary ) ;
let circuit_primary : NovaAugmentedCircuit < G2 , C1 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_primary . clone ( ) ,
Some ( inputs_primary ) ,
c_primary . clone ( ) ,
pp . ro_consts_circuit_primary . clone ( ) ,
) ;
let _ = circuit_primary . synthesize ( & mut cs_primary ) ;
let ( l_u_primary , l_w_primary ) = cs_primary
. r1cs_instance_and_witness ( & pp . r1cs_shape_primary , & pp . ck_primary )
. map_err ( | _e | NovaError ::UnSat )
. expect ( "Nova error unsat" ) ;
// fold the primary circuit's instance
let ( nifs_primary , ( r_U_primary , r_W_primary ) ) = NIFS ::prove (
& pp . ck_primary ,
& pp . ro_consts_primary ,
& pp . digest ,
& pp . r1cs_shape_primary ,
& self . r_U_primary ,
& self . r_W_primary ,
& l_u_primary ,
& l_w_primary ,
)
. expect ( "Unable to fold primary" ) ;
let mut cs_secondary : SatisfyingAssignment < G2 > = SatisfyingAssignment ::new ( ) ;
let inputs_secondary : NovaAugmentedCircuitInputs < G1 > = NovaAugmentedCircuitInputs ::new (
pp . digest ,
G2 ::Scalar ::from ( self . i as u64 ) ,
z0_secondary ,
Some ( self . zi_secondary . clone ( ) ) ,
Some ( self . r_U_primary . clone ( ) ) ,
Some ( l_u_primary ) ,
Some ( Commitment ::< G1 > ::decompress ( & nifs_primary . comm_T ) ? ) ,
) ;
// Outputs of the two circuits thus far
let zi_primary = c_primary . output ( & z0_primary ) ;
let zi_secondary = c_secondary . output ( & z0_secondary ) ;
let circuit_secondary : NovaAugmentedCircuit < G1 , C2 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_secondary . clone ( ) ,
Some ( inputs_secondary ) ,
c_secondary . clone ( ) ,
pp . ro_consts_circuit_secondary . clone ( ) ,
) ;
let _ = circuit_secondary . synthesize ( & mut cs_secondary ) ;
if zi_primary . len ( ) ! = pp . F_arity_primary | | zi_secondary . len ( ) ! = pp . F_arity_secondary {
return Err ( NovaError ::InvalidStepOutputLength ) ;
}
let ( l_u_secondary , l_w_secondary ) = cs_secondary
. r1cs_instance_and_witness ( & pp . r1cs_shape_secondary , & pp . ck_secondary )
. map_err ( | _e | NovaError ::UnSat ) ? ;
Ok ( Self {
r_W_primary ,
r_U_primary ,
r_W_secondary ,
r_U_secondary ,
l_w_secondary ,
l_u_secondary ,
i : 1_ usize ,
zi_primary ,
zi_secondary ,
_p_c1 : Default ::default ( ) ,
_p_c2 : Default ::default ( ) ,
} )
}
Some ( r_snark ) = > {
// fold the secondary circuit's instance
let ( nifs_secondary , ( r_U_secondary , r_W_secondary ) ) = NIFS ::prove (
& pp . ck_secondary ,
& pp . ro_consts_secondary ,
& scalar_as_base ::< G1 > ( pp . digest ) ,
& pp . r1cs_shape_secondary ,
& r_snark . r_U_secondary ,
& r_snark . r_W_secondary ,
& r_snark . l_u_secondary ,
& r_snark . l_w_secondary ,
) ? ;
let mut cs_primary : SatisfyingAssignment < G1 > = SatisfyingAssignment ::new ( ) ;
let inputs_primary : NovaAugmentedCircuitInputs < G2 > = NovaAugmentedCircuitInputs ::new (
scalar_as_base ::< G1 > ( pp . digest ) ,
G1 ::Scalar ::from ( r_snark . i as u64 ) ,
z0_primary ,
Some ( r_snark . zi_primary . clone ( ) ) ,
Some ( r_snark . r_U_secondary . clone ( ) ) ,
Some ( r_snark . l_u_secondary . clone ( ) ) ,
Some ( Commitment ::< G2 > ::decompress ( & nifs_secondary . comm_T ) ? ) ,
) ;
// update the running instances and witnesses
self . zi_primary = c_primary . output ( & self . zi_primary ) ;
self . zi_secondary = c_secondary . output ( & self . zi_secondary ) ;
let circuit_primary : NovaAugmentedCircuit < G2 , C1 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_primary . clone ( ) ,
Some ( inputs_primary ) ,
c_primary . clone ( ) ,
pp . ro_consts_circuit_primary . clone ( ) ,
) ;
let _ = circuit_primary . synthesize ( & mut cs_primary ) ;
self . l_u_secondary = l_u_secondary ;
self . l_w_secondary = l_w_secondary ;
let ( l_u_primary , l_w_primary ) = cs_primary
. r1cs_instance_and_witness ( & pp . r1cs_shape_primary , & pp . ck_primary )
. map_err ( | _e | NovaError ::UnSat ) ? ;
self . r_U_primary = r_U_primary ;
self . r_W_primary = r_W_primary ;
// fold the primary circuit's instance
let ( nifs_primary , ( r_U_primary , r_W_primary ) ) = NIFS ::prove (
& pp . ck_primary ,
& pp . ro_consts_primary ,
& pp . digest ,
& pp . r1cs_shape_primary ,
& r_snark . r_U_primary ,
& r_snark . r_W_primary ,
& l_u_primary ,
& l_w_primary ,
) ? ;
let mut cs_secondary : SatisfyingAssignment < G2 > = SatisfyingAssignment ::new ( ) ;
let inputs_secondary : NovaAugmentedCircuitInputs < G1 > = NovaAugmentedCircuitInputs ::new (
pp . digest ,
G2 ::Scalar ::from ( r_snark . i as u64 ) ,
z0_secondary ,
Some ( r_snark . zi_secondary . clone ( ) ) ,
Some ( r_snark . r_U_primary . clone ( ) ) ,
Some ( l_u_primary ) ,
Some ( Commitment ::< G1 > ::decompress ( & nifs_primary . comm_T ) ? ) ,
) ;
self . i + = 1 ;
let circuit_secondary : NovaAugmentedCircuit < G1 , C2 > = NovaAugmentedCircuit ::new (
pp . augmented_circuit_params_secondary . clone ( ) ,
Some ( inputs_secondary ) ,
c_secondary . clone ( ) ,
pp . ro_consts_circuit_secondary . clone ( ) ,
) ;
let _ = circuit_secondary . synthesize ( & mut cs_secondary ) ;
let ( l_u_secondary , l_w_secondary ) = cs_secondary
. r1cs_instance_and_witness ( & pp . r1cs_shape_secondary , & pp . ck_secondary )
. map_err ( | _e | NovaError ::UnSat ) ? ;
// update the running instances and witnesses
let zi_primary = c_primary . output ( & r_snark . zi_primary ) ;
let zi_secondary = c_secondary . output ( & r_snark . zi_secondary ) ;
Ok ( Self {
r_W_primary ,
r_U_primary ,
r_W_secondary ,
r_U_secondary ,
l_w_secondary ,
l_u_secondary ,
i : r_snark . i + 1 ,
zi_primary ,
zi_secondary ,
_p_c1 : Default ::default ( ) ,
_p_c2 : Default ::default ( ) ,
} )
}
}
self . r_U_secondary = r_U_secondary ;
self . r_W_secondary = r_W_secondary ;
Ok ( ( ) )
}
/// Verify the correctness of the `RecursiveSNARK`
@ -390,8 +400,8 @@ where
& self ,
pp : & PublicParams < G1 , G2 , C1 , C2 > ,
num_steps : usize ,
z0_primary : Vec < G1 ::Scalar > ,
z0_secondary : Vec < G2 ::Scalar > ,
z0_primary : & [ G1 ::Scalar ] ,
z0_secondary : & [ G2 ::Scalar ] ,
) -> Result < ( Vec < G1 ::Scalar > , Vec < G2 ::Scalar > ) , NovaError > {
// number of steps cannot be zero
if num_steps = = 0 {
@ -419,7 +429,7 @@ where
) ;
hasher . absorb ( pp . digest ) ;
hasher . absorb ( G1 ::Scalar ::from ( num_steps as u64 ) ) ;
for e in & z0_primary {
for e in z0_primary {
hasher . absorb ( * e ) ;
}
for e in & self . zi_primary {
@ -433,7 +443,7 @@ where
) ;
hasher2 . absorb ( scalar_as_base ::< G1 > ( pp . digest ) ) ;
hasher2 . absorb ( G2 ::Scalar ::from ( num_steps as u64 ) ) ;
for e in & z0_secondary {
for e in z0_secondary {
hasher2 . absorb ( * e ) ;
}
for e in & self . zi_secondary {
@ -906,23 +916,30 @@ mod tests {
let num_steps = 1 ;
// produce a recursive SNARK
let res = RecursiveSNARK ::prove_step (
let mut recur sive_snark = RecursiveSNARK ::new (
& pp ,
None ,
test_circuit1 ,
test_circuit2 ,
& test_circuit1 ,
& test_circuit2 ,
vec ! [ < G1 as Group > ::Scalar ::ZERO ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
let res = recursive_snark . prove_step (
& pp ,
& test_circuit1 ,
& test_circuit2 ,
vec ! [ < G1 as Group > ::Scalar ::ZERO ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
let recursive_snark = res . unwrap ( ) ;
// verify the recursive SNARK
let res = recursive_snark . verify (
& pp ,
num_steps ,
vec ! [ < G1 as Group > ::Scalar ::ZERO ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
& vec ! [ < G1 as Group > ::Scalar ::ZERO ] [ . . ] ,
& vec ! [ < G2 as Group > ::Scalar ::ZERO ] [ . . ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
}
@ -953,49 +970,45 @@ mod tests {
let num_steps = 3 ;
// produce a recursive SNARK
let mut recursive_snark : Option <
RecursiveSNARK <
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ,
> = None ;
let mut recursive_snark = RecursiveSNARK ::<
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ::new (
& pp ,
& circuit_primary ,
& circuit_secondary ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
for i in 0 . . num_steps {
let res = RecursiveSNARK ::prove_step (
let res = recursive_snark . prove_step (
& pp ,
recursive_snark ,
circuit_primary . clone ( ) ,
circuit_secondary . clone ( ) ,
& circuit_primary ,
& circuit_secondary ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
let recursive_snark_unwrapped = res . unwrap ( ) ;
// verify the recursive snark at each step of recursion
let res = recursive_snark_unwrapped . verify (
let res = recursive_snark . verify (
& pp ,
i + 1 ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
& vec ! [ < G1 as Group > ::Scalar ::ONE ] [ . . ] ,
& vec ! [ < G2 as Group > ::Scalar ::ZERO ] [ . . ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
// set the running variable for the next iteration
recursive_snark = Some ( recursive_snark_unwrapped ) ;
}
assert ! ( recursive_snark . is_some ( ) ) ;
let recursive_snark = recursive_snark . unwrap ( ) ;
// verify the recursive SNARK
let res = recursive_snark . verify (
& pp ,
num_steps ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
& vec ! [ < G1 as Group > ::Scalar ::ONE ] [ . . ] ,
& vec ! [ < G2 as Group > ::Scalar ::ZERO ] [ . . ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
@ -1043,37 +1056,36 @@ mod tests {
let num_steps = 3 ;
// produce a recursive SNARK
let mut recursive_snark : Option <
RecursiveSNARK <
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ,
> = None ;
let mut recursive_snark = RecursiveSNARK ::<
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ::new (
& pp ,
& circuit_primary ,
& circuit_secondary ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
for _i in 0 . . num_steps {
let res = RecursiveSNARK ::prove_step (
let res = recursive_snark . prove_step (
& pp ,
recursive_snark ,
circuit_primary . clone ( ) ,
circuit_secondary . clone ( ) ,
& circuit_primary ,
& circuit_secondary ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
recursive_snark = Some ( res . unwrap ( ) ) ;
}
assert ! ( recursive_snark . is_some ( ) ) ;
let recursive_snark = recursive_snark . unwrap ( ) ;
// verify the recursive SNARK
let res = recursive_snark . verify (
& pp ,
num_steps ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
& vec ! [ < G1 as Group > ::Scalar ::ONE ] [ . . ] ,
& vec ! [ < G2 as Group > ::Scalar ::ZERO ] [ . . ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
@ -1138,37 +1150,36 @@ mod tests {
let num_steps = 3 ;
// produce a recursive SNARK
let mut recursive_snark : Option <
RecursiveSNARK <
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ,
> = None ;
let mut recursive_snark = RecursiveSNARK ::<
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ::new (
& pp ,
& circuit_primary ,
& circuit_secondary ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
for _i in 0 . . num_steps {
let res = RecursiveSNARK ::prove_step (
let res = recursive_snark . prove_step (
& pp ,
recursive_snark ,
circuit_primary . clone ( ) ,
circuit_secondary . clone ( ) ,
& circuit_primary ,
& circuit_secondary ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
recursive_snark = Some ( res . unwrap ( ) ) ;
}
assert ! ( recursive_snark . is_some ( ) ) ;
let recursive_snark = recursive_snark . unwrap ( ) ;
// verify the recursive SNARK
let res = recursive_snark . verify (
& pp ,
num_steps ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
& vec ! [ < G1 as Group > ::Scalar ::ONE ] [ . . ] ,
& vec ! [ < G2 as Group > ::Scalar ::ZERO ] [ . . ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
@ -1237,14 +1248,9 @@ mod tests {
let rng = & mut rand ::rngs ::OsRng ;
let mut seed = F ::random ( rng ) ;
for _i in 0 . . num_steps + 1 {
let mut power = seed ;
power = power . square ( ) ;
power = power . square ( ) ;
power * = seed ;
seed * = seed . clone ( ) . square ( ) . square ( ) ;
powers . push ( Self { y : power } ) ;
seed = power ;
powers . push ( Self { y : seed } ) ;
}
// reverse the powers to get roots
@ -1289,12 +1295,7 @@ mod tests {
fn output ( & self , z : & [ F ] ) -> Vec < F > {
// sanity check
let x = z [ 0 ] ;
let y_pow_5 = {
let y = self . y ;
let y_sq = y . square ( ) ;
let y_quad = y_sq . square ( ) ;
y_quad * self . y
} ;
let y_pow_5 = self . y * self . y . clone ( ) . square ( ) . square ( ) ;
assert_eq ! ( x , y_pow_5 ) ;
// return non-deterministic advice
@ -1324,33 +1325,37 @@ mod tests {
let z0_secondary = vec ! [ < G2 as Group > ::Scalar ::ZERO ] ;
// produce a recursive SNARK
let mut recursive_snark : Option <
RecursiveSNARK <
G1 ,
G2 ,
FifthRootCheckingCircuit < < G1 as Group > ::Scalar > ,
TrivialTestCircuit < < G2 as Group > ::Scalar > ,
> ,
> = None ;
let mut recursive_snark : RecursiveSNARK <
G1 ,
G2 ,
FifthRootCheckingCircuit < < G1 as Group > ::Scalar > ,
TrivialTestCircuit < < G2 as Group > ::Scalar > ,
> = RecursiveSNARK ::<
G1 ,
G2 ,
FifthRootCheckingCircuit < < G1 as Group > ::Scalar > ,
TrivialTestCircuit < < G2 as Group > ::Scalar > ,
> ::new (
& pp ,
& roots [ 0 ] ,
& circuit_secondary ,
z0_primary . clone ( ) ,
z0_secondary . clone ( ) ,
) ;
for circuit_primary in roots . iter ( ) . take ( num_steps ) {
let res = RecursiveSNARK ::prove_step (
let res = recursive_snark . prove_step (
& pp ,
recursive_snark ,
circuit_primary . clone ( ) ,
circuit_secondary . clone ( ) ,
circuit_primary ,
& circuit_secondary . clone ( ) ,
z0_primary . clone ( ) ,
z0_secondary . clone ( ) ,
) ;
assert ! ( res . is_ok ( ) ) ;
recursive_snark = Some ( res . unwrap ( ) ) ;
}
assert ! ( recursive_snark . is_some ( ) ) ;
let recursive_snark = recursive_snark . unwrap ( ) ;
// verify the recursive SNARK
let res = recursive_snark . verify ( & pp , num_steps , z0_primary . clone ( ) , z0_secondary . clone ( ) ) ;
let res = recursive_snark . verify ( & pp , num_steps , & z0_primary , & z0_secondary ) ;
assert ! ( res . is_ok ( ) ) ;
// produce the prover and verifier keys for compressed snark
@ -1379,34 +1384,50 @@ mod tests {
G1 : Group < Base = < G2 as Group > ::Scalar > ,
G2 : Group < Base = < G1 as Group > ::Scalar > ,
{
let test_circuit1 = TrivialTestCircuit ::< < G1 as Group > ::Scalar > ::default ( ) ;
let test_circuit2 = CubicCircuit ::< < G2 as Group > ::Scalar > ::default ( ) ;
// produce public parameters
let pp = PublicParams ::<
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ::setup ( TrivialTestCircuit ::default ( ) , CubicCircuit ::default ( ) ) ;
> ::setup ( test_circuit1 . clone ( ) , test_circuit2 . clone ( ) ) ;
let num_steps = 1 ;
// produce a recursive SNARK
let res = RecursiveSNARK ::prove_step (
let mut recursive_snark = RecursiveSNARK ::<
G1 ,
G2 ,
TrivialTestCircuit < < G1 as Group > ::Scalar > ,
CubicCircuit < < G2 as Group > ::Scalar > ,
> ::new (
& pp ,
None ,
TrivialTestCircuit ::default ( ) ,
CubicCircuit ::default ( ) ,
& test_circuit1 ,
& test_circuit2 ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
// produce a recursive SNARK
let res = recursive_snark . prove_step (
& pp ,
& test_circuit1 ,
& test_circuit2 ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
) ;
assert ! ( res . is_ok ( ) ) ;
let recursive_snark = res . unwrap ( ) ;
// verify the recursive SNARK
let res = recursive_snark . verify (
& pp ,
num_steps ,
vec ! [ < G1 as Group > ::Scalar ::ONE ] ,
vec ! [ < G2 as Group > ::Scalar ::ZERO ] ,
& vec ! [ < G1 as Group > ::Scalar ::ONE ] [ . . ] ,
& vec ! [ < G2 as Group > ::Scalar ::ZERO ] [ . . ] ,
) ;
assert ! ( res . is_ok ( ) ) ;