Browse Source

[test-only] More genericity in tests (#171)

* refactor: make circuit tests generic wrt curves

- Improve modularity by introducing generic `test_recursive_circuit_with` function in `src/circuit.rs`
- Refactor `test_recursive_circuit` to utilize the new function
- Implement type constraints for `test_recursive_circuit_with` function

* refactor: make bellperson tests generic in type of group

- Introduce `test_alloc_bit_with` function utilizing generic types
- Adapt existing `test_alloc_bit` function to use the new `test_alloc_bit_with` function with correct types

* refactor: make the nifs test generic in the type of group

* refactor: make the ivc tests generic in the type of curve

* refactor: simplify generics in tests

* make the keccak tests generic

* make the poseidon tests generic

* make the spartan tests generic
main
François Garillot 1 year ago
committed by GitHub
parent
commit
54f758eef3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 227 additions and 96 deletions
  1. +17
    -8
      src/bellperson/mod.rs
  2. +34
    -18
      src/circuit.rs
  3. +15
    -22
      src/gadgets/ecc.rs
  4. +111
    -26
      src/lib.rs
  5. +15
    -6
      src/nifs.rs
  6. +7
    -4
      src/provider/keccak.rs
  7. +21
    -10
      src/provider/poseidon.rs
  8. +7
    -2
      src/spartan/pp.rs

+ 17
- 8
src/bellperson/mod.rs

@ -8,10 +8,13 @@ pub mod solver;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::bellperson::{
r1cs::{NovaShape, NovaWitness},
shape_cs::ShapeCS,
solver::SatisfyingAssignment,
use crate::{
bellperson::{
r1cs::{NovaShape, NovaWitness},
shape_cs::ShapeCS,
solver::SatisfyingAssignment,
},
traits::Group,
}; };
use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
use ff::PrimeField; use ff::PrimeField;
@ -39,10 +42,10 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn test_alloc_bit() {
type G = pasta_curves::pallas::Point;
fn test_alloc_bit_with<G>()
where
G: Group,
{
// First create the shape // First create the shape
let mut cs: ShapeCS<G> = ShapeCS::new(); let mut cs: ShapeCS<G> = ShapeCS::new();
let _ = synthesize_alloc_bit(&mut cs); let _ = synthesize_alloc_bit(&mut cs);
@ -56,4 +59,10 @@ mod tests {
// Make sure that this is satisfiable // Make sure that this is satisfiable
assert!(shape.is_sat(&ck, &inst, &witness).is_ok()); assert!(shape.is_sat(&ck, &inst, &witness).is_ok());
} }
#[test]
fn test_alloc_bit() {
type G = pasta_curves::pallas::Point;
test_alloc_bit_with::<G>();
}
} }

+ 34
- 18
src/circuit.rs

@ -372,8 +372,8 @@ impl> Circuit<::Base>
mod tests { mod tests {
use super::*; use super::*;
use crate::bellperson::{shape_cs::ShapeCS, solver::SatisfyingAssignment}; use crate::bellperson::{shape_cs::ShapeCS, solver::SatisfyingAssignment};
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
type PastaG1 = pasta_curves::pallas::Point;
type PastaG2 = pasta_curves::vesta::Point;
use crate::constants::{BN_LIMB_WIDTH, BN_N_LIMBS}; use crate::constants::{BN_LIMB_WIDTH, BN_N_LIMBS};
use crate::{ use crate::{
@ -383,18 +383,22 @@ mod tests {
traits::{circuit::TrivialTestCircuit, ROConstantsTrait}, traits::{circuit::TrivialTestCircuit, ROConstantsTrait},
}; };
#[test]
fn test_recursive_circuit() {
// In the following we use 1 to refer to the primary, and 2 to refer to the secondary circuit
let params1 = NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, true);
let params2 = NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, false);
let ro_consts1: ROConstantsCircuit<G2> = PoseidonConstantsCircuit::new();
let ro_consts2: ROConstantsCircuit<G1> = PoseidonConstantsCircuit::new();
// In the following we use 1 to refer to the primary, and 2 to refer to the secondary circuit
fn test_recursive_circuit_with<G1, G2>(
primary_params: NovaAugmentedCircuitParams,
secondary_params: NovaAugmentedCircuitParams,
ro_consts1: ROConstantsCircuit<G2>,
ro_consts2: ROConstantsCircuit<G1>,
num_constraints_primary: usize,
num_constraints_secondary: usize,
) where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
{
// Initialize the shape and ck for the primary // Initialize the shape and ck for the primary
let circuit1: NovaAugmentedCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> = let circuit1: NovaAugmentedCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> =
NovaAugmentedCircuit::new( NovaAugmentedCircuit::new(
params1.clone(),
primary_params.clone(),
None, None,
TrivialTestCircuit::default(), TrivialTestCircuit::default(),
ro_consts1.clone(), ro_consts1.clone(),
@ -402,12 +406,12 @@ mod tests {
let mut cs: ShapeCS<G1> = ShapeCS::new(); let mut cs: ShapeCS<G1> = ShapeCS::new();
let _ = circuit1.synthesize(&mut cs); let _ = circuit1.synthesize(&mut cs);
let (shape1, ck1) = cs.r1cs_shape(); let (shape1, ck1) = cs.r1cs_shape();
assert_eq!(cs.num_constraints(), 9815);
assert_eq!(cs.num_constraints(), num_constraints_primary);
// Initialize the shape and ck for the secondary // Initialize the shape and ck for the secondary
let circuit2: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> = let circuit2: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> =
NovaAugmentedCircuit::new( NovaAugmentedCircuit::new(
params2.clone(),
secondary_params.clone(),
None, None,
TrivialTestCircuit::default(), TrivialTestCircuit::default(),
ro_consts2.clone(), ro_consts2.clone(),
@ -415,7 +419,7 @@ mod tests {
let mut cs: ShapeCS<G2> = ShapeCS::new(); let mut cs: ShapeCS<G2> = ShapeCS::new();
let _ = circuit2.synthesize(&mut cs); let _ = circuit2.synthesize(&mut cs);
let (shape2, ck2) = cs.r1cs_shape(); let (shape2, ck2) = cs.r1cs_shape();
assert_eq!(cs.num_constraints(), 10347);
assert_eq!(cs.num_constraints(), num_constraints_secondary);
// Execute the base case for the primary // Execute the base case for the primary
let zero1 = <<G2 as Group>::Base as Field>::ZERO; let zero1 = <<G2 as Group>::Base as Field>::ZERO;
@ -431,7 +435,7 @@ mod tests {
); );
let circuit1: NovaAugmentedCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> = let circuit1: NovaAugmentedCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> =
NovaAugmentedCircuit::new( NovaAugmentedCircuit::new(
params1,
primary_params,
Some(inputs1), Some(inputs1),
TrivialTestCircuit::default(), TrivialTestCircuit::default(),
ro_consts1, ro_consts1,
@ -453,16 +457,28 @@ mod tests {
Some(inst1), Some(inst1),
None, None,
); );
let circuit: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> =
let circuit2: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> =
NovaAugmentedCircuit::new( NovaAugmentedCircuit::new(
params2,
secondary_params,
Some(inputs2), Some(inputs2),
TrivialTestCircuit::default(), TrivialTestCircuit::default(),
ro_consts2, ro_consts2,
); );
let _ = circuit.synthesize(&mut cs2);
let _ = circuit2.synthesize(&mut cs2);
let (inst2, witness2) = cs2.r1cs_instance_and_witness(&shape2, &ck2).unwrap(); let (inst2, witness2) = cs2.r1cs_instance_and_witness(&shape2, &ck2).unwrap();
// Make sure that it is satisfiable // Make sure that it is satisfiable
assert!(shape2.is_sat(&ck2, &inst2, &witness2).is_ok()); assert!(shape2.is_sat(&ck2, &inst2, &witness2).is_ok());
} }
#[test]
fn test_recursive_circuit() {
let params1 = NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, true);
let params2 = NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, false);
let ro_consts1: ROConstantsCircuit<PastaG2> = PoseidonConstantsCircuit::new();
let ro_consts2: ROConstantsCircuit<PastaG1> = PoseidonConstantsCircuit::new();
test_recursive_circuit_with::<PastaG1, PastaG2>(
params1, params2, ro_consts1, ro_consts2, 9815, 10347,
);
}
} }

+ 15
- 22
src/gadgets/ecc.rs

@ -975,16 +975,14 @@ mod tests {
#[test] #[test]
fn test_ecc_circuit_ops() { fn test_ecc_circuit_ops() {
test_ecc_circuit_ops_with::<pallas::Base, pallas::Scalar, pallas::Point, vesta::Point>();
test_ecc_circuit_ops_with::<vesta::Base, vesta::Scalar, vesta::Point, pallas::Point>();
test_ecc_circuit_ops_with::<pallas::Point, vesta::Point>();
test_ecc_circuit_ops_with::<vesta::Point, pallas::Point>();
} }
fn test_ecc_circuit_ops_with<B, S, G1, G2>()
fn test_ecc_circuit_ops_with<G1, G2>()
where where
B: PrimeField,
S: PrimeField,
G1: Group<Base = B, Scalar = S>,
G2: Group<Base = S, Scalar = B>,
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
{ {
// First create the shape // First create the shape
let mut cs: ShapeCS<G2> = ShapeCS::new(); let mut cs: ShapeCS<G2> = ShapeCS::new();
@ -1027,16 +1025,14 @@ mod tests {
#[test] #[test]
fn test_ecc_circuit_add_equal() { fn test_ecc_circuit_add_equal() {
test_ecc_circuit_add_equal_with::<pallas::Base, pallas::Scalar, pallas::Point, vesta::Point>();
test_ecc_circuit_add_equal_with::<vesta::Base, vesta::Scalar, vesta::Point, pallas::Point>();
test_ecc_circuit_add_equal_with::<pallas::Point, vesta::Point>();
test_ecc_circuit_add_equal_with::<vesta::Point, pallas::Point>();
} }
fn test_ecc_circuit_add_equal_with<B, S, G1, G2>()
fn test_ecc_circuit_add_equal_with<G1, G2>()
where where
B: PrimeField,
S: PrimeField,
G1: Group<Base = B, Scalar = S>,
G2: Group<Base = S, Scalar = B>,
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
{ {
// First create the shape // First create the shape
let mut cs: ShapeCS<G2> = ShapeCS::new(); let mut cs: ShapeCS<G2> = ShapeCS::new();
@ -1083,17 +1079,14 @@ mod tests {
#[test] #[test]
fn test_ecc_circuit_add_negation() { fn test_ecc_circuit_add_negation() {
test_ecc_circuit_add_negation_with::<pallas::Base, pallas::Scalar, pallas::Point, vesta::Point>(
);
test_ecc_circuit_add_negation_with::<vesta::Base, vesta::Scalar, vesta::Point, pallas::Point>();
test_ecc_circuit_add_negation_with::<pallas::Point, vesta::Point>();
test_ecc_circuit_add_negation_with::<vesta::Point, pallas::Point>();
} }
fn test_ecc_circuit_add_negation_with<B, S, G1, G2>()
fn test_ecc_circuit_add_negation_with<G1, G2>()
where where
B: PrimeField,
S: PrimeField,
G1: Group<Base = B, Scalar = S>,
G2: Group<Base = S, Scalar = B>,
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
{ {
// First create the shape // First create the shape
let mut cs: ShapeCS<G2> = ShapeCS::new(); let mut cs: ShapeCS<G2> = ShapeCS::new();

+ 111
- 26
src/lib.rs

@ -787,13 +787,16 @@ fn compute_digest(o: &T) -> G::Scalar {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::provider::pedersen::CommitmentKeyExtTrait;
use super::*; use super::*;
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
type EE1 = provider::ipa_pc::EvaluationEngine<G1>;
type EE2 = provider::ipa_pc::EvaluationEngine<G2>;
type S1 = spartan::RelaxedR1CSSNARK<G1, EE1>;
type S2 = spartan::RelaxedR1CSSNARK<G2, EE2>;
type EE1<G1> = provider::ipa_pc::EvaluationEngine<G1>;
type EE2<G2> = provider::ipa_pc::EvaluationEngine<G2>;
type S1<G1> = spartan::RelaxedR1CSSNARK<G1, EE1<G1>>;
type S2<G2> = spartan::RelaxedR1CSSNARK<G2, EE2<G2>>;
type S1Prime<G1> = spartan::pp::RelaxedR1CSSNARK<G1, EE1<G1>>;
type S2Prime<G2> = spartan::pp::RelaxedR1CSSNARK<G2, EE2<G2>>;
use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
use core::marker::PhantomData; use core::marker::PhantomData;
use ff::PrimeField; use ff::PrimeField;
@ -848,15 +851,21 @@ mod tests {
} }
} }
#[test]
fn test_ivc_trivial() {
fn test_ivc_trivial_with<G1, G2>()
where
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 = TrivialTestCircuit::<<G2 as Group>::Scalar>::default();
// produce public parameters // produce public parameters
let pp = PublicParams::< let pp = PublicParams::<
G1, G1,
G2, G2,
TrivialTestCircuit<<G1 as Group>::Scalar>, TrivialTestCircuit<<G1 as Group>::Scalar>,
TrivialTestCircuit<<G2 as Group>::Scalar>, TrivialTestCircuit<<G2 as Group>::Scalar>,
>::setup(TrivialTestCircuit::default(), TrivialTestCircuit::default());
>::setup(test_circuit1.clone(), test_circuit2.clone());
let num_steps = 1; let num_steps = 1;
@ -864,8 +873,8 @@ mod tests {
let res = RecursiveSNARK::prove_step( let res = RecursiveSNARK::prove_step(
&pp, &pp,
None, None,
TrivialTestCircuit::default(),
TrivialTestCircuit::default(),
test_circuit1,
test_circuit2,
vec![<G1 as Group>::Scalar::ZERO], vec![<G1 as Group>::Scalar::ZERO],
vec![<G2 as Group>::Scalar::ZERO], vec![<G2 as Group>::Scalar::ZERO],
); );
@ -883,7 +892,17 @@ mod tests {
} }
#[test] #[test]
fn test_ivc_nontrivial() {
fn test_ivc_trivial() {
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
test_ivc_trivial_with::<G1, G2>();
}
fn test_ivc_nontrivial_with<G1, G2>()
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
{
let circuit_primary = TrivialTestCircuit::default(); let circuit_primary = TrivialTestCircuit::default();
let circuit_secondary = CubicCircuit::default(); let circuit_secondary = CubicCircuit::default();
@ -950,14 +969,30 @@ mod tests {
assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]); assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]);
let mut zn_secondary_direct = vec![<G2 as Group>::Scalar::ZERO]; let mut zn_secondary_direct = vec![<G2 as Group>::Scalar::ZERO];
for _i in 0..num_steps { for _i in 0..num_steps {
zn_secondary_direct = CubicCircuit::default().output(&zn_secondary_direct);
zn_secondary_direct = circuit_secondary.clone().output(&zn_secondary_direct);
} }
assert_eq!(zn_secondary, zn_secondary_direct); assert_eq!(zn_secondary, zn_secondary_direct);
assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(2460515u64)]); assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(2460515u64)]);
} }
#[test] #[test]
fn test_ivc_nontrivial_with_compression() {
fn test_ivc_nontrivial() {
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
test_ivc_nontrivial_with::<G1, G2>();
}
fn test_ivc_nontrivial_with_compression_with<G1, G2>()
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
// this is due to the reliance on CommitmentKeyExtTrait as a bound in ipa_pc
<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 circuit_primary = TrivialTestCircuit::default(); let circuit_primary = TrivialTestCircuit::default();
let circuit_secondary = CubicCircuit::default(); let circuit_secondary = CubicCircuit::default();
@ -1012,16 +1047,16 @@ mod tests {
assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]); assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]);
let mut zn_secondary_direct = vec![<G2 as Group>::Scalar::ZERO]; let mut zn_secondary_direct = vec![<G2 as Group>::Scalar::ZERO];
for _i in 0..num_steps { for _i in 0..num_steps {
zn_secondary_direct = CubicCircuit::default().output(&zn_secondary_direct);
zn_secondary_direct = circuit_secondary.clone().output(&zn_secondary_direct);
} }
assert_eq!(zn_secondary, zn_secondary_direct); assert_eq!(zn_secondary, zn_secondary_direct);
assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(2460515u64)]); assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(2460515u64)]);
// produce the prover and verifier keys for compressed snark // produce the prover and verifier keys for compressed snark
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap();
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1<G1>, S2<G2>>::setup(&pp).unwrap();
// produce a compressed SNARK // produce a compressed SNARK
let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark);
let res = CompressedSNARK::<_, _, _, _, S1<G1>, S2<G2>>::prove(&pp, &pk, &recursive_snark);
assert!(res.is_ok()); assert!(res.is_ok());
let compressed_snark = res.unwrap(); let compressed_snark = res.unwrap();
@ -1036,7 +1071,23 @@ mod tests {
} }
#[test] #[test]
fn test_ivc_nontrivial_with_spark_compression() {
fn test_ivc_nontrivial_with_compression() {
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
test_ivc_nontrivial_with_compression_with::<G1, G2>();
}
fn test_ivc_nontrivial_with_spark_compression_with<G1, G2>()
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
// this is due to the reliance on CommitmentKeyExtTrait as a bound in ipa_pc
<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 circuit_primary = TrivialTestCircuit::default(); let circuit_primary = TrivialTestCircuit::default();
let circuit_secondary = CubicCircuit::default(); let circuit_secondary = CubicCircuit::default();
@ -1097,14 +1148,13 @@ mod tests {
assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(2460515u64)]); assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(2460515u64)]);
// run the compressed snark with Spark compiler // run the compressed snark with Spark compiler
type S1Prime = spartan::pp::RelaxedR1CSSNARK<G1, EE1>;
type S2Prime = spartan::pp::RelaxedR1CSSNARK<G2, EE2>;
// produce the prover and verifier keys for compressed snark // produce the prover and verifier keys for compressed snark
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1Prime, S2Prime>::setup(&pp).unwrap();
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1Prime<G1>, S2Prime<G2>>::setup(&pp).unwrap();
// produce a compressed SNARK // produce a compressed SNARK
let res = CompressedSNARK::<_, _, _, _, S1Prime, S2Prime>::prove(&pp, &pk, &recursive_snark);
let res =
CompressedSNARK::<_, _, _, _, S1Prime<G1>, S2Prime<G2>>::prove(&pp, &pk, &recursive_snark);
assert!(res.is_ok()); assert!(res.is_ok());
let compressed_snark = res.unwrap(); let compressed_snark = res.unwrap();
@ -1119,7 +1169,23 @@ mod tests {
} }
#[test] #[test]
fn test_ivc_nondet_with_compression() {
fn test_ivc_nontrivial_with_spark_compression() {
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
test_ivc_nontrivial_with_spark_compression_with::<G1, G2>();
}
fn test_ivc_nondet_with_compression_with<G1, G2>()
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
// this is due to the reliance on CommitmentKeyExtTrait as a bound in ipa_pc
<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>,
{
// y is a non-deterministic advice representing the fifth root of the input at a step. // y is a non-deterministic advice representing the fifth root of the input at a step.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct FifthRootCheckingCircuit<F: PrimeField> { struct FifthRootCheckingCircuit<F: PrimeField> {
@ -1252,10 +1318,10 @@ mod tests {
assert!(res.is_ok()); assert!(res.is_ok());
// produce the prover and verifier keys for compressed snark // produce the prover and verifier keys for compressed snark
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap();
let (pk, vk) = CompressedSNARK::<_, _, _, _, S1<G1>, S2<G2>>::setup(&pp).unwrap();
// produce a compressed SNARK // produce a compressed SNARK
let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark);
let res = CompressedSNARK::<_, _, _, _, S1<G1>, S2<G2>>::prove(&pp, &pk, &recursive_snark);
assert!(res.is_ok()); assert!(res.is_ok());
let compressed_snark = res.unwrap(); let compressed_snark = res.unwrap();
@ -1265,7 +1331,18 @@ mod tests {
} }
#[test] #[test]
fn test_ivc_base() {
fn test_ivc_nondet_with_compression() {
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
test_ivc_nondet_with_compression_with::<G1, G2>();
}
fn test_ivc_base_with<G1, G2>()
where
G1: Group<Base = <G2 as Group>::Scalar>,
G2: Group<Base = <G1 as Group>::Scalar>,
{
// produce public parameters // produce public parameters
let pp = PublicParams::< let pp = PublicParams::<
G1, G1,
@ -1302,4 +1379,12 @@ mod tests {
assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]); assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]);
assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(5u64)]); assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(5u64)]);
} }
#[test]
fn test_ivc_base() {
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
test_ivc_base_with::<G1, G2>();
}
} }

+ 15
- 6
src/nifs.rs

@ -162,8 +162,10 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn test_tiny_r1cs_bellperson() {
fn test_tiny_r1cs_bellperson_with<G>()
where
G: Group,
{
use crate::bellperson::{ use crate::bellperson::{
r1cs::{NovaShape, NovaWitness}, r1cs::{NovaShape, NovaWitness},
shape_cs::ShapeCS, shape_cs::ShapeCS,
@ -179,7 +181,7 @@ mod tests {
// Now get the instance and assignment for one instance // Now get the instance and assignment for one instance
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new(); let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
let _ = synthesize_tiny_r1cs_bellperson(&mut cs, Some(S::from(5)));
let _ = synthesize_tiny_r1cs_bellperson(&mut cs, Some(G::Scalar::from(5)));
let (U1, W1) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); let (U1, W1) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap();
// Make sure that the first instance is satisfiable // Make sure that the first instance is satisfiable
@ -187,7 +189,7 @@ mod tests {
// Now get the instance and assignment for second instance // Now get the instance and assignment for second instance
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new(); let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
let _ = synthesize_tiny_r1cs_bellperson(&mut cs, Some(S::from(135)));
let _ = synthesize_tiny_r1cs_bellperson(&mut cs, Some(G::Scalar::from(135)));
let (U2, W2) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap(); let (U2, W2) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap();
// Make sure that the second instance is satisfiable // Make sure that the second instance is satisfiable
@ -206,8 +208,13 @@ mod tests {
); );
} }
#[test]
fn test_tiny_r1cs_bellperson() {
test_tiny_r1cs_bellperson_with::<G>();
}
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn execute_sequence(
fn execute_sequence<G>(
ck: &CommitmentKey<G>, ck: &CommitmentKey<G>,
ro_consts: &<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants, ro_consts: &<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants,
pp_digest: &<G as Group>::Scalar, pp_digest: &<G as Group>::Scalar,
@ -216,7 +223,9 @@ mod tests {
W1: &R1CSWitness<G>, W1: &R1CSWitness<G>,
U2: &R1CSInstance<G>, U2: &R1CSInstance<G>,
W2: &R1CSWitness<G>, W2: &R1CSWitness<G>,
) {
) where
G: Group,
{
// produce a default running instance // produce a default running instance
let mut r_W = RelaxedR1CSWitness::default(shape); let mut r_W = RelaxedR1CSWitness::default(shape);
let mut r_U = RelaxedR1CSInstance::default(ck, shape); let mut r_U = RelaxedR1CSInstance::default(ck, shape);

+ 7
- 4
src/provider/keccak.rs

@ -101,10 +101,7 @@ mod tests {
use ff::PrimeField; use ff::PrimeField;
use sha3::{Digest, Keccak256}; use sha3::{Digest, Keccak256};
type G = pasta_curves::pallas::Point;
#[test]
fn test_keccak_transcript() {
fn test_keccak_transcript_with<G: Group>() {
let mut transcript: Keccak256Transcript<G> = Keccak256Transcript::new(b"test"); let mut transcript: Keccak256Transcript<G> = Keccak256Transcript::new(b"test");
// two scalars // two scalars
@ -136,6 +133,12 @@ mod tests {
); );
} }
#[test]
fn test_keccak_transcript() {
type G = pasta_curves::pallas::Point;
test_keccak_transcript_with::<G>()
}
#[test] #[test]
fn test_keccak_example() { fn test_keccak_example() {
let mut hasher = Keccak256::new(); let mut hasher = Keccak256::new();

+ 21
- 10
src/provider/poseidon.rs

@ -201,27 +201,31 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
type S = pasta_curves::pallas::Scalar;
type B = pasta_curves::vesta::Scalar;
type G = pasta_curves::pallas::Point;
use crate::{ use crate::{
bellperson::solver::SatisfyingAssignment, constants::NUM_CHALLENGE_BITS, bellperson::solver::SatisfyingAssignment, constants::NUM_CHALLENGE_BITS,
gadgets::utils::le_bits_to_num,
gadgets::utils::le_bits_to_num, traits::Group,
}; };
use ff::Field; use ff::Field;
use rand::rngs::OsRng; use rand::rngs::OsRng;
#[test]
fn test_poseidon_ro() {
fn test_poseidon_ro_with<G: Group>()
where
// we can print the field elements we get from G's Base & Scalar fields,
// and compare their byte representations
<<G as Group>::Base as PrimeField>::Repr: std::fmt::Debug,
<<G as Group>::Scalar as PrimeField>::Repr: std::fmt::Debug,
<<G as Group>::Base as PrimeField>::Repr: PartialEq<<<G as Group>::Scalar as PrimeField>::Repr>,
{
// Check that the number computed inside the circuit is equal to the number computed outside the circuit // Check that the number computed inside the circuit is equal to the number computed outside the circuit
let mut csprng: OsRng = OsRng; let mut csprng: OsRng = OsRng;
let constants = PoseidonConstantsCircuit::new();
let constants = PoseidonConstantsCircuit::<G::Scalar>::new();
let num_absorbs = 32; let num_absorbs = 32;
let mut ro: PoseidonRO<S, B> = PoseidonRO::new(constants.clone(), num_absorbs);
let mut ro_gadget: PoseidonROCircuit<S> = PoseidonROCircuit::new(constants, num_absorbs);
let mut ro: PoseidonRO<G::Scalar, G::Base> = PoseidonRO::new(constants.clone(), num_absorbs);
let mut ro_gadget: PoseidonROCircuit<G::Scalar> =
PoseidonROCircuit::new(constants, num_absorbs);
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new(); let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
for i in 0..num_absorbs { for i in 0..num_absorbs {
let num = S::random(&mut csprng);
let num = G::Scalar::random(&mut csprng);
ro.absorb(num); ro.absorb(num);
let num_gadget = let num_gadget =
AllocatedNum::alloc(cs.namespace(|| format!("data {i}")), || Ok(num)).unwrap(); AllocatedNum::alloc(cs.namespace(|| format!("data {i}")), || Ok(num)).unwrap();
@ -235,4 +239,11 @@ mod tests {
let num2 = le_bits_to_num(&mut cs, num2_bits).unwrap(); let num2 = le_bits_to_num(&mut cs, num2_bits).unwrap();
assert_eq!(num.to_repr(), num2.get_value().unwrap().to_repr()); assert_eq!(num.to_repr(), num2.get_value().unwrap().to_repr());
} }
#[test]
fn test_poseidon_ro() {
type G = pasta_curves::pallas::Point;
test_poseidon_ro_with::<G>()
}
} }

+ 7
- 2
src/spartan/pp.rs

@ -2191,8 +2191,6 @@ impl, C: StepCircuit
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
type G = pasta_curves::pallas::Point;
type EE = crate::provider::ipa_pc::EvaluationEngine<G>;
use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
use core::marker::PhantomData; use core::marker::PhantomData;
use ff::PrimeField; use ff::PrimeField;
@ -2248,6 +2246,13 @@ mod tests {
#[test] #[test]
fn test_spartan_snark() { fn test_spartan_snark() {
type G = pasta_curves::pallas::Point;
type EE = crate::provider::ipa_pc::EvaluationEngine<G>;
test_spartan_snark_with::<G, EE>();
}
fn test_spartan_snark_with<G: Group, EE: EvaluationEngineTrait<G, CE = G::CE>>() {
let circuit = CubicCircuit::default(); let circuit = CubicCircuit::default();
// produce keys // produce keys

Loading…
Cancel
Save