@@ -164,8 +164,12 @@ impl<I: InnerCircuit> RecursiveCircuit<I> {
164164
165165 /// builds the targets and returns also a ProverCircuitData
166166 pub fn build ( params : & RecursiveParams , inner_params : & I :: Params ) -> Result < Self > {
167+ #[ cfg( not( feature = "zk" ) ) ]
167168 let config = CircuitConfig :: standard_recursion_config ( ) ;
168- let mut builder = CircuitBuilder :: new ( config. clone ( ) ) ;
169+ #[ cfg( feature = "zk" ) ]
170+ let config = CircuitConfig :: standard_recursion_zk_config ( ) ;
171+
172+ let mut builder = CircuitBuilder :: new ( config) ;
169173
170174 let targets: RecursiveCircuitTarget < I > = Self :: build_targets (
171175 & mut builder,
@@ -275,7 +279,11 @@ impl<I: InnerCircuit> RecursiveCircuit<I> {
275279 ) ;
276280
277281 // build the actual RecursiveCircuit circuit data
282+ #[ cfg( not( feature = "zk" ) ) ]
278283 let config = CircuitConfig :: standard_recursion_config ( ) ;
284+ #[ cfg( feature = "zk" ) ]
285+ let config = CircuitConfig :: standard_recursion_zk_config ( ) ;
286+
279287 let mut builder = CircuitBuilder :: new ( config) ;
280288
281289 let target = timed ! (
@@ -295,7 +303,11 @@ impl<I: InnerCircuit> RecursiveCircuit<I> {
295303 inner_params : & I :: Params ,
296304 ) -> Result < ( RecursiveCircuitTarget < I > , CircuitData < F , C , D > ) > {
297305 // build the actual RecursiveCircuit circuit data
306+ #[ cfg( not( feature = "zk" ) ) ]
298307 let config = CircuitConfig :: standard_recursion_config ( ) ;
308+ #[ cfg( feature = "zk" ) ]
309+ let config = CircuitConfig :: standard_recursion_zk_config ( ) ;
310+
299311 let mut builder = CircuitBuilder :: new ( config) ;
300312
301313 let target = timed ! (
@@ -398,9 +410,20 @@ fn standard_gates(config: &CircuitConfig) -> Vec<GateRef<F, D>> {
398410/// Estimate the number of gates to verify a proof of `degree_bits` that uses the
399411/// `standard_gates(&standard_recursion_config)`
400412fn estimate_verif_num_gates ( degree_bits : usize ) -> usize {
401- // Formula obtained via linear regression using `test_measure_recursion` results with
402- // `standard_recursion_config`.
403- let num_gates: usize = 236 * degree_bits + 1171 ;
413+ let num_gates: usize ;
414+
415+ #[ cfg( feature = "zk" ) ]
416+ {
417+ // Formula obtained via linear regression using
418+ // `test_measure_zk_recursion` results with `standard_recursion_zk_config`.
419+ num_gates = 244 * degree_bits + 1127 ;
420+ }
421+ #[ cfg( not( feature = "zk" ) ) ]
422+ {
423+ // Formula obtained via linear regression using `test_measure_recursion`
424+ // results with `standard_recursion_config`.
425+ let num_gates: usize = 236 * degree_bits + 1171 ;
426+ }
404427 // Add 2% for error because the results are not a clean line
405428 num_gates * 102 / 100
406429}
@@ -417,6 +440,21 @@ fn estimate_gates_after_zk(degree_bits: usize) -> usize {
417440 }
418441}
419442
443+ // how many blinding gates are in this zk circuit
444+ fn blinding_gates ( degree_bits : usize ) -> usize {
445+ // Table data obtained using `test_measure_zk_recursion`, and printing
446+ // `regular_poly_openings + 2 * z_openings` at method `blind` of the file
447+ // `plonky2/plonky2/src/plonk/circuit_builder.rs`.
448+ match degree_bits {
449+ 0 ..=12 => 8326 ,
450+ 13 ..=14 => 8998 ,
451+ 15 => 10342 ,
452+ 16 => 13030 ,
453+ 17 => 10846 ,
454+ _ => panic ! ( "not supported" ) ,
455+ }
456+ }
457+
420458pub fn common_data_for_recursion < I : InnerCircuit > (
421459 arity : usize ,
422460 num_public_inputs : usize ,
@@ -448,13 +486,22 @@ pub fn common_data_for_recursion<I: InnerCircuit>(
448486 let mut degree_bits = log2_ceil ( inner_num_gates) ;
449487 loop {
450488 let verif_num_gates = estimate_verif_num_gates ( degree_bits) ;
451- // Leave space for public input hashing, a `PublicInputGate` and some `ConstantGate`s (that's
452- // MAX_CONSTANT_GATES*2 constants in the standard_recursion_config).
453- let total_num_gates = inner_num_gates
489+
490+ // Leave space for public input hashing, a `PublicInputGate` and some
491+ // `ConstantGate`s (that's MAX_CONSTANT_GATES*2 constants in the
492+ // standard_recursion_config). And if the zk feature is enabled, add
493+ // space for the blinding gates.
494+ let mut total_num_gates = inner_num_gates
454495 + verif_num_gates * arity
455496 + circuit_data. common . num_public_inputs . div_ceil ( 8 )
456497 + 1
457498 + MAX_CONSTANT_GATES ;
499+
500+ #[ cfg( feature = "zk" ) ]
501+ {
502+ total_num_gates += blinding_gates ( degree_bits) ;
503+ }
504+
458505 if total_num_gates < ( 1 << degree_bits) {
459506 break ;
460507 }
@@ -464,27 +511,36 @@ pub fn common_data_for_recursion<I: InnerCircuit>(
464511 let mut common_data = circuit_data. common . clone ( ) ;
465512 common_data. fri_params . degree_bits = degree_bits;
466513 common_data. fri_params . reduction_arity_bits = vec ! [ 4 , 4 , 4 ] ;
514+ #[ cfg( feature = "zk" ) ]
515+ {
516+ common_data. fri_params . hiding = true ;
517+ common_data. config . zero_knowledge = true ;
518+ }
467519 Ok ( common_data)
468520}
469521
470522/// Pad the circuit to match a given `CommonCircuitData`.
471523pub fn pad_circuit ( builder : & mut CircuitBuilder < F , D > , common_data : & CommonCircuitData < F , D > ) {
472524 assert_eq ! ( common_data. config, builder. config) ;
473525 assert_eq ! ( common_data. num_public_inputs, builder. num_public_inputs( ) ) ;
474- // TODO: We need to figure this out once we enable zero-knowledge
475- // https://github.com/0xPARC/pod2/issues/248
476- assert ! (
477- !common_data. config. zero_knowledge,
478- "Degree calculation can be off if zero-knowledge is on."
479- ) ;
480526
481527 let degree = common_data. degree ( ) ;
482528 // Need to account for public input hashing, a `PublicInputGate` and MAX_CONSTANT_GATES
483529 // `ConstantGate`. NOTE: the builder doesn't have any public method to see how many constants
484530 // have been registered, so we can't know exactly how many `ConstantGates` will be required.
485531 // We hope that no more than MAX_CONSTANT_GATES*2 constants are used :pray:. Maybe we should
486532 // make a PR to plonky2 to expose this?
487- let num_gates = degree - common_data. num_public_inputs . div_ceil ( 8 ) - 1 - MAX_CONSTANT_GATES ;
533+ let mut num_gates = degree - common_data. num_public_inputs . div_ceil ( 8 ) - 1 - MAX_CONSTANT_GATES ;
534+ #[ cfg( feature = "zk" ) ]
535+ {
536+ // in the zk config case, account for the blinding gates, to avoid
537+ // padding to them too, because then plonky2's in the builder.build()
538+ // phase would add new blinding gates on top of the ones that we already
539+ // accounted for in the `common_data_for_recursion`, increasing (w.h.p.)
540+ // the degree of the circuit.
541+ num_gates -= blinding_gates ( log2_ceil ( degree) ) ;
542+ }
543+
488544 assert ! (
489545 builder. num_gates( ) < num_gates,
490546 "builder has more gates ({}) than the padding target ({})" ,
@@ -678,22 +734,22 @@ mod tests {
678734 }
679735
680736 #[ test]
681- fn test_circuit_i ( ) -> Result < ( ) > {
737+ fn test_inner_circuit_i ( ) -> Result < ( ) > {
682738 let inner_params = ( ) ;
683739 let inp = HashOut :: < F > :: ZERO ;
684740
685741 let inner_inputs = ( inp, circuit1_io ( inp) ) ;
686- test_circuit_i_opt :: < Circuit1 > ( & inner_params, inner_inputs) ?;
742+ test_inner_circuit_i_opt :: < Circuit1 > ( & inner_params, inner_inputs) ?;
687743
688744 let inner_inputs = ( inp, circuit2_io ( inp) ) ;
689- test_circuit_i_opt :: < Circuit2 > ( & inner_params, inner_inputs) ?;
745+ test_inner_circuit_i_opt :: < Circuit2 > ( & inner_params, inner_inputs) ?;
690746
691747 let inner_inputs = ( inp, circuit3_io ( inp) ) ;
692- test_circuit_i_opt :: < Circuit3 > ( & inner_params, inner_inputs) ?;
748+ test_inner_circuit_i_opt :: < Circuit3 > ( & inner_params, inner_inputs) ?;
693749
694750 Ok ( ( ) )
695751 }
696- fn test_circuit_i_opt < IC : InnerCircuit > (
752+ fn test_inner_circuit_i_opt < IC : InnerCircuit > (
697753 inner_params : & IC :: Params ,
698754 inner_inputs : IC :: Input ,
699755 ) -> Result < ( ) > {
0 commit comments