Skip to content

Commit

Permalink
feat: Make commitment key generation configurable with an optional pa…
Browse files Browse the repository at this point in the history
…rameter

- Implemented the `Len` trait within `CommitmentKey` to allow length quantification in terms of group generators. Made ppSnark fail setup if given commitment key with insufficient length,
  as measured by its own commitment_key_floor() (see below)
- Made RelaxedR1CSTrait include a fn commitment_key_floor() -> Box<dyn for<'a> Fn(&'a R1CSShape<G>) -> usize> with default implementation to quantify the Snark's commitment key size requirements
  in the shape of a closure,
- Made PublicParameters accept optional Box<dyn for<'a> Fn(&'a R1CSShape<G>) -> usize> parameters for each circuit's group, to parametrize the CommitmentKey creation.

Implementation details:
- defined type alias CommitmentKeyHint<G> = Box<dyn Fn(&R1CSShape<G>) -> usize>; (only used internally)
- Modified numerous function calls and parameter setups to include optional parameter `CommitmentKeyHint` that gives a more flexible commitment key generation.
- Added the `CommitmentKeyHint` to the `r1cs` import list and expanded `NovaShape` trait to optionally accept it.
  • Loading branch information
huitseeker committed Aug 4, 2023
1 parent 155bbfc commit 1acbf8c
Show file tree
Hide file tree
Showing 17 changed files with 165 additions and 39 deletions.
15 changes: 13 additions & 2 deletions benches/compressed-snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use ff::PrimeField;
use nova_snark::{
traits::{
circuit::{StepCircuit, TrivialTestCircuit},
snark::RelaxedR1CSSNARKTrait,
Group,
},
CompressedSNARK, PublicParams, RecursiveSNARK,
Expand Down Expand Up @@ -65,7 +66,12 @@ fn bench_compressed_snark(c: &mut Criterion) {
let c_secondary = TrivialTestCircuit::default();

// Produce public parameters
let pp = PublicParams::<G1, G2, C1, C2>::setup(&c_primary, &c_secondary);
let pp = PublicParams::<G1, G2, C1, C2>::setup(
&c_primary,
&c_secondary,
Some(S1::commitment_key_floor()),
Some(S2::commitment_key_floor()),
);

// Produce prover and verifier keys for CompressedSNARK
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap();
Expand Down Expand Up @@ -152,7 +158,12 @@ fn bench_compressed_snark_with_computational_commitments(c: &mut Criterion) {
let c_secondary = TrivialTestCircuit::default();

// Produce public parameters
let pp = PublicParams::<G1, G2, C1, C2>::setup(&c_primary, &c_secondary);
let pp = PublicParams::<G1, G2, C1, C2>::setup(
&c_primary,
&c_secondary,
Some(SS1::commitment_key_floor()),
Some(SS2::commitment_key_floor()),
);

// Produce prover and verifier keys for CompressedSNARK
let (pk, vk) = CompressedSNARK::<_, _, _, _, SS1, SS2>::setup(&pp).unwrap();
Expand Down
7 changes: 6 additions & 1 deletion benches/compute-digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ criterion_main!(compute_digest);
fn bench_compute_digest(c: &mut Criterion) {
c.bench_function("compute_digest", |b| {
b.iter(|| {
PublicParams::<G1, G2, C1, C2>::setup(black_box(&C1::new(10)), black_box(&C2::default()))
PublicParams::<G1, G2, C1, C2>::setup(
black_box(&C1::new(10)),
black_box(&C2::default()),
black_box(None),
black_box(None),
)
})
});
}
Expand Down
2 changes: 1 addition & 1 deletion benches/recursive-snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn bench_recursive_snark(c: &mut Criterion) {
let c_secondary = TrivialTestCircuit::default();

// Produce public parameters
let pp = PublicParams::<G1, G2, C1, C2>::setup(&c_primary, &c_secondary);
let pp = PublicParams::<G1, G2, C1, C2>::setup(&c_primary, &c_secondary, None, None);

// Bench time to produce a recursive SNARK;
// we execute a certain number of warm-up steps since executing
Expand Down
2 changes: 1 addition & 1 deletion benches/sha256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ fn bench_recursive_snark(c: &mut Criterion) {

// Produce public parameters
let ttc = TrivialTestCircuit::default();
let pp = PublicParams::<G1, G2, C1, C2>::setup(&circuit_primary, &ttc);
let pp = PublicParams::<G1, G2, C1, C2>::setup(&circuit_primary, &ttc, None, None);

let circuit_secondary = TrivialTestCircuit::default();
let z0_primary = vec![<G1 as Group>::Scalar::from(2u64)];
Expand Down
2 changes: 1 addition & 1 deletion examples/minroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ fn main() {
G2,
MinRootCircuit<<G1 as Group>::Scalar>,
TrivialTestCircuit<<G2 as Group>::Scalar>,
>::setup(&circuit_primary, &circuit_secondary);
>::setup(&circuit_primary, &circuit_secondary, None, None);
println!("PublicParams::setup, took {:?} ", start.elapsed());

println!(
Expand Down
2 changes: 1 addition & 1 deletion src/bellperson/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ mod tests {
// First create the shape
let mut cs: ShapeCS<G> = ShapeCS::new();
let _ = synthesize_alloc_bit(&mut cs);
let (shape, ck) = cs.r1cs_shape();
let (shape, ck) = cs.r1cs_shape(None);

// Now get the assignment
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
Expand Down
10 changes: 6 additions & 4 deletions src/bellperson/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use super::{shape_cs::ShapeCS, solver::SatisfyingAssignment};
use crate::{
errors::NovaError,
r1cs::{R1CSInstance, R1CSShape, R1CSWitness, R1CS},
r1cs::{CommitmentKeyHint, R1CSInstance, R1CSShape, R1CSWitness, R1CS},
traits::Group,
CommitmentKey,
};
Expand All @@ -25,7 +25,9 @@ pub trait NovaWitness<G: Group> {
/// `NovaShape` provides methods for acquiring `R1CSShape` and `CommitmentKey` from implementers.
pub trait NovaShape<G: Group> {
/// Return an appropriate `R1CSShape` and `CommitmentKey` structs.
fn r1cs_shape(&self) -> (R1CSShape<G>, CommitmentKey<G>);
/// Optionally, a `CommitmentKeyHint` can be provided to help guide the
/// construction of the `CommitmentKey`. This parameter is documented in `r1cs::R1CS::commitment_key`.
fn r1cs_shape(&self, optfn: Option<CommitmentKeyHint<G>>) -> (R1CSShape<G>, CommitmentKey<G>);
}

impl<G: Group> NovaWitness<G> for SatisfyingAssignment<G> {
Expand All @@ -46,7 +48,7 @@ impl<G: Group> NovaWitness<G> for SatisfyingAssignment<G> {
}

impl<G: Group> NovaShape<G> for ShapeCS<G> {
fn r1cs_shape(&self) -> (R1CSShape<G>, CommitmentKey<G>) {
fn r1cs_shape(&self, optfn: Option<CommitmentKeyHint<G>>) -> (R1CSShape<G>, CommitmentKey<G>) {
let mut A: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut B: Vec<(usize, usize, G::Scalar)> = Vec::new();
let mut C: Vec<(usize, usize, G::Scalar)> = Vec::new();
Expand Down Expand Up @@ -76,7 +78,7 @@ impl<G: Group> NovaShape<G> for ShapeCS<G> {
res.unwrap()
};

let ck = R1CS::<G>::commitment_key(&S);
let ck = R1CS::<G>::commitment_key(&S, optfn);

(S, ck)
}
Expand Down
4 changes: 2 additions & 2 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ mod tests {
NovaAugmentedCircuit::new(&primary_params, None, &ttc1, ro_consts1.clone());
let mut cs: ShapeCS<G1> = ShapeCS::new();
let _ = circuit1.synthesize(&mut cs);
let (shape1, ck1) = cs.r1cs_shape();
let (shape1, ck1) = cs.r1cs_shape(None);
assert_eq!(cs.num_constraints(), num_constraints_primary);

let ttc2 = TrivialTestCircuit::default();
Expand All @@ -411,7 +411,7 @@ mod tests {
NovaAugmentedCircuit::new(&secondary_params, None, &ttc2, ro_consts2.clone());
let mut cs: ShapeCS<G2> = ShapeCS::new();
let _ = circuit2.synthesize(&mut cs);
let (shape2, ck2) = cs.r1cs_shape();
let (shape2, ck2) = cs.r1cs_shape(None);
assert_eq!(cs.num_constraints(), num_constraints_secondary);

// Execute the base case for the primary
Expand Down
6 changes: 3 additions & 3 deletions src/gadgets/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ mod tests {
let mut cs: ShapeCS<G2> = ShapeCS::new();
let _ = synthesize_smul::<G1, _>(cs.namespace(|| "synthesize"));
println!("Number of constraints: {}", cs.num_constraints());
let (shape, ck) = cs.r1cs_shape();
let (shape, ck) = cs.r1cs_shape(None);

// Then the satisfying assignment
let mut cs: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
Expand Down Expand Up @@ -1047,7 +1047,7 @@ mod tests {
let mut cs: ShapeCS<G2> = ShapeCS::new();
let _ = synthesize_add_equal::<G1, _>(cs.namespace(|| "synthesize add equal"));
println!("Number of constraints: {}", cs.num_constraints());
let (shape, ck) = cs.r1cs_shape();
let (shape, ck) = cs.r1cs_shape(None);

// Then the satisfying assignment
let mut cs: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
Expand Down Expand Up @@ -1104,7 +1104,7 @@ mod tests {
let mut cs: ShapeCS<G2> = ShapeCS::new();
let _ = synthesize_add_negation::<G1, _>(cs.namespace(|| "synthesize add equal"));
println!("Number of constraints: {}", cs.num_constraints());
let (shape, ck) = cs.r1cs_shape();
let (shape, ck) = cs.r1cs_shape(None);

// Then the satisfying assignment
let mut cs: SatisfyingAssignment<G2> = SatisfyingAssignment::new();
Expand Down
85 changes: 72 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ use errors::NovaError;
use ff::Field;
use gadgets::utils::scalar_as_base;
use nifs::NIFS;
use r1cs::{R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness};
use r1cs::{
CommitmentKeyHint, R1CSInstance, R1CSShape, R1CSWitness, RelaxedR1CSInstance, RelaxedR1CSWitness,
};
use serde::{Deserialize, Serialize};
use sha3::{Digest, Sha3_256};
use traits::{
Expand Down Expand Up @@ -82,8 +84,53 @@ where
C1: StepCircuit<G1::Scalar>,
C2: StepCircuit<G2::Scalar>,
{
/// Create a new `PublicParams`
pub fn setup(c_primary: &C1, c_secondary: &C2) -> Self {
/// Creates a new `PublicParams` for a pair of circuits `C1` and `C2`.
///
/// # Note
///
/// Some SNARKs, like variants of Spartan, use computation commitments that require
/// larger sizes for some 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 `None` instead.
///
/// # Arguments
///
/// * `c_primary`: The primary circuit of type `C1`.
/// * `c_secondary`: The secondary circuit of type `C2`.
/// * `optfn1`: An optional `CommitmentKeyHint` for `G1`, which is a function that provides a hint
/// for the number of generators required in the commitment scheme for the primary circuit.
/// * `optfn2`: An optional `CommitmentKeyHint` for `G2`, similar to `optfn1`, but for the secondary circuit.
///
/// # Example
///
/// ```rust
/// # use pasta_curves::{vesta, pallas};
/// # use nova_snark::spartan::ppsnark::RelaxedR1CSSNARK;
/// # use nova_snark::provider::ipa_pc::EvaluationEngine;
/// # use nova_snark::traits::{circuit::TrivialTestCircuit, Group, snark::RelaxedR1CSSNARKTrait};
/// use nova_snark::PublicParams;
///
/// type G1 = pallas::Point;
/// type G2 = vesta::Point;
/// type EE1<G1> = EvaluationEngine<G1>;
/// type EE2<G2> = EvaluationEngine<G2>;
/// type S1Prime<G1> = RelaxedR1CSSNARK<G1, EE1<G1>>;
/// type S2Prime<G2> = RelaxedR1CSSNARK<G2, EE2<G2>>;
///
/// let circuit1 = TrivialTestCircuit::<<G1 as Group>::Scalar>::default();
/// let circuit2 = TrivialTestCircuit::<<G2 as Group>::Scalar>::default();
/// // Only relevant for a SNARK using computational commitments, pass None otherwise.
/// let pp_hint1 = Some(S1Prime::<G1>::commitment_key_floor());
/// let pp_hint2 = Some(S2Prime::<G2>::commitment_key_floor());
///
/// let pp = PublicParams::setup(circuit1, circuit2, pp_hint1, pp_hint2);
/// ```
pub fn setup(
c_primary: &C1,
c_secondary: &C2,
optfn1: Option<CommitmentKeyHint<G1>>,
optfn2: Option<CommitmentKeyHint<G2>>,
) -> Self {
let augmented_circuit_params_primary =
NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, true);
let augmented_circuit_params_secondary =
Expand All @@ -108,7 +155,7 @@ where
);
let mut cs: ShapeCS<G1> = ShapeCS::new();
let _ = circuit_primary.synthesize(&mut cs);
let (r1cs_shape_primary, ck_primary) = cs.r1cs_shape();
let (r1cs_shape_primary, ck_primary) = cs.r1cs_shape(optfn1);

// Initialize ck for the secondary
let circuit_secondary: NovaAugmentedCircuit<'_, G1, C2> = NovaAugmentedCircuit::new(
Expand All @@ -119,7 +166,7 @@ where
);
let mut cs: ShapeCS<G2> = ShapeCS::new();
let _ = circuit_secondary.synthesize(&mut cs);
let (r1cs_shape_secondary, ck_secondary) = cs.r1cs_shape();
let (r1cs_shape_secondary, ck_secondary) = cs.r1cs_shape(optfn2);

let mut pp = Self {
F_arity_primary,
Expand Down Expand Up @@ -864,8 +911,15 @@ mod tests {
G2: Group<Base = <G1 as Group>::Scalar>,
T1: StepCircuit<G1::Scalar>,
T2: StepCircuit<G2::Scalar>,
<G1::CE as CommitmentEngineTrait<G1>>::CommitmentKey:
CommitmentKeyExtTrait<G1, CE = <G1 as Group>::CE>,
<G2::CE as CommitmentEngineTrait<G2>>::CommitmentKey:
CommitmentKeyExtTrait<G2, CE = <G2 as Group>::CE>,
{
let pp = PublicParams::<G1, G2, T1, T2>::setup(&circuit1, &circuit2);
// this tests public parameters with a size specifically intended for a spark-compressed SNARK
let pp_hint1 = Some(S1Prime::<G1>::commitment_key_floor());
let pp_hint2 = Some(S2Prime::<G2>::commitment_key_floor());
let pp = PublicParams::<G1, G2, T1, T2>::setup(&circuit1, &circuit2, pp_hint1, pp_hint2);

let digest_str = pp
.digest
Expand Down Expand Up @@ -929,7 +983,7 @@ mod tests {
G2,
TrivialTestCircuit<<G1 as Group>::Scalar>,
TrivialTestCircuit<<G2 as Group>::Scalar>,
>::setup(&test_circuit1, &test_circuit2);
>::setup(&test_circuit1, &test_circuit2, None, None);

let num_steps = 1;

Expand Down Expand Up @@ -985,7 +1039,7 @@ mod tests {
G2,
TrivialTestCircuit<<G1 as Group>::Scalar>,
CubicCircuit<<G2 as Group>::Scalar>,
>::setup(&circuit_primary, &circuit_secondary);
>::setup(&circuit_primary, &circuit_secondary, None, None);

let num_steps = 3;

Expand Down Expand Up @@ -1072,7 +1126,7 @@ mod tests {
G2,
TrivialTestCircuit<<G1 as Group>::Scalar>,
CubicCircuit<<G2 as Group>::Scalar>,
>::setup(&circuit_primary, &circuit_secondary);
>::setup(&circuit_primary, &circuit_secondary, None, None);

let num_steps = 3;

Expand Down Expand Up @@ -1161,13 +1215,18 @@ mod tests {
let circuit_primary = TrivialTestCircuit::default();
let circuit_secondary = CubicCircuit::default();

// produce public parameters
// produce public parameters, which we'll use with a spark-compressed SNARK
let pp = PublicParams::<
G1,
G2,
TrivialTestCircuit<<G1 as Group>::Scalar>,
CubicCircuit<<G2 as Group>::Scalar>,
>::setup(&circuit_primary, &circuit_secondary);
>::setup(
&circuit_primary,
&circuit_secondary,
Some(S1Prime::commitment_key_floor()),
Some(S2Prime::commitment_key_floor()),
);

let num_steps = 3;

Expand Down Expand Up @@ -1339,7 +1398,7 @@ mod tests {
G2,
FifthRootCheckingCircuit<<G1 as Group>::Scalar>,
TrivialTestCircuit<<G2 as Group>::Scalar>,
>::setup(&circuit_primary, &circuit_secondary);
>::setup(&circuit_primary, &circuit_secondary, None, None);

let num_steps = 3;

Expand Down Expand Up @@ -1417,7 +1476,7 @@ mod tests {
G2,
TrivialTestCircuit<<G1 as Group>::Scalar>,
CubicCircuit<<G2 as Group>::Scalar>,
>::setup(&test_circuit1, &test_circuit2);
>::setup(&test_circuit1, &test_circuit2, None, None);

let num_steps = 1;

Expand Down
4 changes: 2 additions & 2 deletions src/nifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ mod tests {
// First create the shape
let mut cs: ShapeCS<G> = ShapeCS::new();
let _ = synthesize_tiny_r1cs_bellperson(&mut cs, None);
let (shape, ck) = cs.r1cs_shape();
let (shape, ck) = cs.r1cs_shape(None);
let ro_consts =
<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants::new();

Expand Down Expand Up @@ -326,7 +326,7 @@ mod tests {
};

// generate generators and ro constants
let ck = R1CS::<G>::commitment_key(&S);
let ck = R1CS::<G>::commitment_key(&S, None);
let ro_consts =
<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants::new();

Expand Down
8 changes: 7 additions & 1 deletion src/provider/pedersen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use crate::{
errors::NovaError,
traits::{
commitment::{CommitmentEngineTrait, CommitmentTrait},
commitment::{CommitmentEngineTrait, CommitmentTrait, Len},
AbsorbInROTrait, CompressedGroup, Group, ROTrait, TranscriptReprTrait,
},
};
Expand All @@ -22,6 +22,12 @@ pub struct CommitmentKey<G: Group> {
_p: PhantomData<G>,
}

impl<G: Group> Len for CommitmentKey<G> {
fn len(&self) -> usize {
self.ck.len()
}
}

/// A type that holds a commitment
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(bound = "")]
Expand Down
Loading

0 comments on commit 1acbf8c

Please sign in to comment.