From e4793755101b06774d375a5708dfa5f251fb4329 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= <francois@garillot.net>
Date: Fri, 3 Nov 2023 10:34:33 -0400
Subject: [PATCH] feat: Refactor to use `default_commitment_key_hint` across
 codebase

- Introduced a new function `default_commitment_key_hint` in `nova_snark` package to provide a clearer default sizing hint for the commitment key,
- Replaced hard-coded zero values throughout the codebase with calls to `default_commitment_key_hint` function,
---
 benches/compute-digest.rs  |  5 +++--
 benches/recursive-snark.rs |  4 ++--
 benches/sha256.rs          |  4 ++--
 examples/minroot.rs        |  4 ++--
 src/bellpepper/mod.rs      |  4 ++--
 src/circuit.rs             |  7 ++++---
 src/gadgets/ecc.rs         | 10 +++++-----
 src/lib.rs                 | 13 +++++++------
 src/nifs.rs                |  6 +++---
 src/traits/snark.rs        | 11 ++++++++++-
 10 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/benches/compute-digest.rs b/benches/compute-digest.rs
index 249d7bd9e..dca32580a 100644
--- a/benches/compute-digest.rs
+++ b/benches/compute-digest.rs
@@ -5,6 +5,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
 use ff::PrimeField;
 use nova_snark::{
   traits::{
+    snark::default_commitment_key_hint,
     circuit::{StepCircuit, TrivialCircuit},
     Group,
   },
@@ -30,8 +31,8 @@ fn bench_compute_digest(c: &mut Criterion) {
       PublicParams::<G1, G2, C1, C2>::setup(
         black_box(&C1::new(10)),
         black_box(&C2::default()),
-        black_box(&(|_| 0)),
-        black_box(&(|_| 0)),
+        black_box(&*default_commitment_key_hint()),
+        black_box(&*default_commitment_key_hint()),
       )
     })
   });
diff --git a/benches/recursive-snark.rs b/benches/recursive-snark.rs
index c59c8c86c..23800da9f 100644
--- a/benches/recursive-snark.rs
+++ b/benches/recursive-snark.rs
@@ -7,7 +7,7 @@ use ff::PrimeField;
 use nova_snark::{
   traits::{
     circuit::{StepCircuit, TrivialCircuit},
-    Group,
+    Group, snark::default_commitment_key_hint,
   },
   PublicParams, RecursiveSNARK,
 };
@@ -56,7 +56,7 @@ fn bench_recursive_snark(c: &mut Criterion) {
     let c_secondary = TrivialCircuit::default();
 
     // Produce public parameters
-    let pp = PublicParams::<G1, G2, C1, C2>::setup(&c_primary, &c_secondary, &(|_| 0), &(|_| 0));
+    let pp = PublicParams::<G1, G2, C1, C2>::setup(&c_primary, &c_secondary, &*default_commitment_key_hint(), &*default_commitment_key_hint());
 
     // Bench time to produce a recursive SNARK;
     // we execute a certain number of warm-up steps since executing
diff --git a/benches/sha256.rs b/benches/sha256.rs
index 192ae3d77..001c622ed 100644
--- a/benches/sha256.rs
+++ b/benches/sha256.rs
@@ -17,7 +17,7 @@ use ff::{PrimeField, PrimeFieldBits};
 use nova_snark::{
   traits::{
     circuit::{StepCircuit, TrivialCircuit},
-    Group,
+    Group, snark::default_commitment_key_hint,
   },
   PublicParams, RecursiveSNARK,
 };
@@ -155,7 +155,7 @@ fn bench_recursive_snark(c: &mut Criterion) {
 
     // Produce public parameters
     let ttc = TrivialCircuit::default();
-    let pp = PublicParams::<G1, G2, C1, C2>::setup(&circuit_primary, &ttc, &(|_| 0), &(|_| 0));
+    let pp = PublicParams::<G1, G2, C1, C2>::setup(&circuit_primary, &ttc, &*default_commitment_key_hint(), &*default_commitment_key_hint());
 
     let circuit_secondary = TrivialCircuit::default();
     let z0_primary = vec![<G1 as Group>::Scalar::from(2u64)];
diff --git a/examples/minroot.rs b/examples/minroot.rs
index 66809af8b..36d222477 100644
--- a/examples/minroot.rs
+++ b/examples/minroot.rs
@@ -9,7 +9,7 @@ use flate2::{write::ZlibEncoder, Compression};
 use nova_snark::{
   traits::{
     circuit::{StepCircuit, TrivialCircuit},
-    Group,
+    Group, snark::default_commitment_key_hint,
   },
   CompressedSNARK, PublicParams, RecursiveSNARK,
 };
@@ -161,7 +161,7 @@ fn main() {
       G2,
       MinRootCircuit<<G1 as Group>::Scalar>,
       TrivialCircuit<<G2 as Group>::Scalar>,
-    >::setup(&circuit_primary, &circuit_secondary, &(|_| 0), &(|_| 0));
+    >::setup(&circuit_primary, &circuit_secondary, &*default_commitment_key_hint(), &*default_commitment_key_hint());
     println!("PublicParams::setup, took {:?} ", start.elapsed());
 
     println!(
diff --git a/src/bellpepper/mod.rs b/src/bellpepper/mod.rs
index 4809786d3..df7d5249b 100644
--- a/src/bellpepper/mod.rs
+++ b/src/bellpepper/mod.rs
@@ -15,7 +15,7 @@ mod tests {
       shape_cs::ShapeCS,
       solver::SatisfyingAssignment,
     },
-    traits::Group,
+    traits::{Group, snark::default_commitment_key_hint},
   };
   use bellpepper_core::{num::AllocatedNum, ConstraintSystem};
   use ff::PrimeField;
@@ -47,7 +47,7 @@ mod tests {
     // First create the shape
     let mut cs: ShapeCS<G> = ShapeCS::new();
     synthesize_alloc_bit(&mut cs);
-    let (shape, ck) = cs.r1cs_shape(&(|_| 0));
+    let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint());
 
     // Now get the assignment
     let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
diff --git a/src/circuit.rs b/src/circuit.rs
index 1ed2bab64..c2274dcb7 100644
--- a/src/circuit.rs
+++ b/src/circuit.rs
@@ -367,7 +367,8 @@ mod tests {
 
   use crate::constants::{BN_LIMB_WIDTH, BN_N_LIMBS};
   use crate::provider;
-  use crate::{
+  use crate::traits::snark::default_commitment_key_hint;
+use crate::{
     bellpepper::r1cs::{NovaShape, NovaWitness},
     gadgets::utils::scalar_as_base,
     provider::poseidon::PoseidonConstantsCircuit,
@@ -392,7 +393,7 @@ mod tests {
       NovaAugmentedCircuit::new(primary_params, None, &tc1, ro_consts1.clone());
     let mut cs: TestShapeCS<G1> = TestShapeCS::new();
     let _ = circuit1.synthesize(&mut cs);
-    let (shape1, ck1) = cs.r1cs_shape(&(|_| 0));
+    let (shape1, ck1) = cs.r1cs_shape(&*default_commitment_key_hint());
     assert_eq!(cs.num_constraints(), num_constraints_primary);
 
     let tc2 = TrivialCircuit::default();
@@ -401,7 +402,7 @@ mod tests {
       NovaAugmentedCircuit::new(secondary_params, None, &tc2, ro_consts2.clone());
     let mut cs: TestShapeCS<G2> = TestShapeCS::new();
     let _ = circuit2.synthesize(&mut cs);
-    let (shape2, ck2) = cs.r1cs_shape(&(|_| 0));
+    let (shape2, ck2) = cs.r1cs_shape(&*default_commitment_key_hint());
     assert_eq!(cs.num_constraints(), num_constraints_secondary);
 
     // Execute the base case for the primary
diff --git a/src/gadgets/ecc.rs b/src/gadgets/ecc.rs
index a85434f82..9cfc1cef1 100644
--- a/src/gadgets/ecc.rs
+++ b/src/gadgets/ecc.rs
@@ -748,10 +748,10 @@ where
 #[cfg(test)]
 mod tests {
   use super::*;
-  use crate::bellpepper::{
+  use crate::{bellpepper::{
     r1cs::{NovaShape, NovaWitness},
     {solver::SatisfyingAssignment, test_shape_cs::TestShapeCS},
-  };
+  }, traits::snark::default_commitment_key_hint};
   use crate::provider::{
     bn256_grumpkin::{bn256, grumpkin},
     secp_secq::{secp256k1, secq256k1},
@@ -1000,7 +1000,7 @@ mod tests {
     let mut cs: TestShapeCS<G2> = TestShapeCS::new();
     let _ = synthesize_smul::<G1, _>(cs.namespace(|| "synthesize"));
     println!("Number of constraints: {}", cs.num_constraints());
-    let (shape, ck) = cs.r1cs_shape(&(|_| 0));
+    let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint());
 
     // Then the satisfying assignment
     let mut cs: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
@@ -1056,7 +1056,7 @@ mod tests {
     let mut cs: TestShapeCS<G2> = TestShapeCS::new();
     let _ = synthesize_add_equal::<G1, _>(cs.namespace(|| "synthesize add equal"));
     println!("Number of constraints: {}", cs.num_constraints());
-    let (shape, ck) = cs.r1cs_shape(&(|_| 0));
+    let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint());
 
     // Then the satisfying assignment
     let mut cs: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
@@ -1116,7 +1116,7 @@ mod tests {
     let mut cs: TestShapeCS<G2> = TestShapeCS::new();
     let _ = synthesize_add_negation::<G1, _>(cs.namespace(|| "synthesize add equal"));
     println!("Number of constraints: {}", cs.num_constraints());
-    let (shape, ck) = cs.r1cs_shape(&(|_| 0));
+    let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint());
 
     // Then the satisfying assignment
     let mut cs: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
diff --git a/src/lib.rs b/src/lib.rs
index 1168a5fd4..144cad79f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -105,7 +105,7 @@ where
   /// larger sizes for these parameters. These SNARKs provide a hint for these values by
   /// implementing `RelaxedR1CSSNARKTrait::commitment_key_floor()`, which can be passed to this function.
   /// 
-  /// If you're not using such a SNARK, pass `&(|_| 0)` instead.
+  /// If you're not using such a SNARK, pass `nova_snark::traits::snark::default_commitment_key_hint()` instead.
   ///
   /// # Arguments
   ///
@@ -866,6 +866,7 @@ mod tests {
   use crate::provider::pedersen::CommitmentKeyExtTrait;
   use crate::provider::secp_secq::{secp256k1, secq256k1};
   use crate::traits::evaluation::EvaluationEngineTrait;
+  use crate::traits::snark::default_commitment_key_hint;
   use core::fmt::Write;
 
   use super::*;
@@ -1024,7 +1025,7 @@ mod tests {
       G2,
       TrivialCircuit<<G1 as Group>::Scalar>,
       TrivialCircuit<<G2 as Group>::Scalar>,
-    >::setup(&test_circuit1, &test_circuit2, &(|_| 0), &(|_| 0));
+    >::setup(&test_circuit1, &test_circuit2, &*default_commitment_key_hint(), &*default_commitment_key_hint());
 
     let num_steps = 1;
 
@@ -1076,7 +1077,7 @@ mod tests {
       G2,
       TrivialCircuit<<G1 as Group>::Scalar>,
       CubicCircuit<<G2 as Group>::Scalar>,
-    >::setup(&circuit_primary, &circuit_secondary, &(|_| 0), &(|_| 0));
+    >::setup(&circuit_primary, &circuit_secondary, &*default_commitment_key_hint(), &*default_commitment_key_hint());
 
     let num_steps = 3;
 
@@ -1156,7 +1157,7 @@ mod tests {
       G2,
       TrivialCircuit<<G1 as Group>::Scalar>,
       CubicCircuit<<G2 as Group>::Scalar>,
-    >::setup(&circuit_primary, &circuit_secondary, &(|_| 0), &(|_| 0));
+    >::setup(&circuit_primary, &circuit_secondary, &*default_commitment_key_hint(), &*default_commitment_key_hint());
 
     let num_steps = 3;
 
@@ -1414,7 +1415,7 @@ mod tests {
       G2,
       FifthRootCheckingCircuit<<G1 as Group>::Scalar>,
       TrivialCircuit<<G2 as Group>::Scalar>,
-    >::setup(&circuit_primary, &circuit_secondary, &(|_| 0), &(|_| 0));
+    >::setup(&circuit_primary, &circuit_secondary, &*default_commitment_key_hint(), &*default_commitment_key_hint());
 
     let num_steps = 3;
 
@@ -1489,7 +1490,7 @@ mod tests {
       G2,
       TrivialCircuit<<G1 as Group>::Scalar>,
       CubicCircuit<<G2 as Group>::Scalar>,
-    >::setup(&test_circuit1, &test_circuit2, &(|_| 0), &(|_| 0));
+    >::setup(&test_circuit1, &test_circuit2, &*default_commitment_key_hint(), &*default_commitment_key_hint());
 
     let num_steps = 1;
 
diff --git a/src/nifs.rs b/src/nifs.rs
index f05cb315a..0d211a2ba 100644
--- a/src/nifs.rs
+++ b/src/nifs.rs
@@ -113,7 +113,7 @@ impl<G: Group> NIFS<G> {
 #[cfg(test)]
 mod tests {
   use super::*;
-  use crate::{r1cs::SparseMatrix, r1cs::R1CS, traits::Group};
+  use crate::{r1cs::SparseMatrix, r1cs::R1CS, traits::Group, traits::snark::default_commitment_key_hint};
   use ::bellpepper_core::{num::AllocatedNum, ConstraintSystem, SynthesisError};
   use ff::{Field, PrimeField};
   use rand::rngs::OsRng;
@@ -166,7 +166,7 @@ mod tests {
     // First create the shape
     let mut cs: TestShapeCS<G> = TestShapeCS::new();
     let _ = synthesize_tiny_r1cs_bellpepper(&mut cs, None);
-    let (shape, ck) = cs.r1cs_shape(&(|_| 0));
+    let (shape, ck) = cs.r1cs_shape(&*default_commitment_key_hint());
     let ro_consts =
       <<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants::default();
 
@@ -327,7 +327,7 @@ mod tests {
     };
 
     // generate generators and ro constants
-    let ck = R1CS::<G>::commitment_key(&S, &(|_| 0));
+    let ck = R1CS::<G>::commitment_key(&S, &*default_commitment_key_hint());
     let ro_consts =
       <<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants::default();
 
diff --git a/src/traits/snark.rs b/src/traits/snark.rs
index 24b293227..84fc32f31 100644
--- a/src/traits/snark.rs
+++ b/src/traits/snark.rs
@@ -8,6 +8,15 @@ use crate::{
 
 use serde::{Deserialize, Serialize};
 
+/// Public parameter creation takes a size hint. This size hint carries the particular requirements of 
+/// the final compressing SNARK the user expected to use with these public parameters, and the below
+/// is a sensible default, which is to not require any more bases then the usual (maximum of the number of
+/// variables and constraints of the involved R1CS circuit).
+pub fn default_commitment_key_hint<G: Group>() -> Box<dyn for<'a> Fn(&'a R1CSShape<G>) -> usize> {
+  // The default is to not put an additional floor on the size of the commitment key
+  Box::new(|_shape: &R1CSShape<G>| 0)
+}
+
 /// A trait that defines the behavior of a `zkSNARK`
 pub trait RelaxedR1CSSNARKTrait<G: Group>:
   Send + Sync + Serialize + for<'de> Deserialize<'de>
@@ -24,7 +33,7 @@ pub trait RelaxedR1CSSNARKTrait<G: Group>:
   /// be at least as large as this hint.
   fn commitment_key_floor() -> Box<dyn for<'a> Fn(&'a R1CSShape<G>) -> usize> {
     // The default is to not put an additional floor on the size of the commitment key
-    Box::new(|_shape: &R1CSShape<G>| 0)
+    default_commitment_key_hint()
   }
 
   /// Produces the keys for the prover and the verifier