arnaucube
arnaucube/NovaPublic Self-hosted repository
[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
François Garillot 4142+huitseeker@users.noreply.github.com
Fri, 26 May 2023 22:43:35 +0200
commit

54f758eef36a42bec189c9f27f153fd7545f6ac3

parent

58fc746c0bb2a22750487479494406fbccfd6a74

M src/bellperson/mod.rs → src/bellperson/mod.rs

@@ -8,10 +8,13 @@ pub mod solver;

#[cfg(test)] 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 ff::PrimeField;

@@ -39,10 +42,10 @@ );

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 let mut cs: ShapeCS<G> = ShapeCS::new(); let _ = synthesize_alloc_bit(&mut cs);

@@ -55,5 +58,11 @@ let (inst, witness) = cs.r1cs_instance_and_witness(&shape, &ck).unwrap();

// Make sure that this is satisfiable 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>(); } }
M src/circuit.rs → src/circuit.rs

@@ -372,8 +372,8 @@ #[cfg(test)]

mod tests { use super::*; 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::{

@@ -383,18 +383,22 @@ provider::poseidon::PoseidonConstantsCircuit,

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 let circuit1: NovaAugmentedCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> = NovaAugmentedCircuit::new( - params1.clone(), + primary_params.clone(), None, TrivialTestCircuit::default(), ro_consts1.clone(),

@@ -402,12 +406,12 @@ );

let mut cs: ShapeCS<G1> = ShapeCS::new(); let _ = circuit1.synthesize(&mut cs); 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 let circuit2: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> = NovaAugmentedCircuit::new( - params2.clone(), + secondary_params.clone(), None, TrivialTestCircuit::default(), ro_consts2.clone(),

@@ -415,7 +419,7 @@ );

let mut cs: ShapeCS<G2> = ShapeCS::new(); let _ = circuit2.synthesize(&mut cs); 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 let zero1 = <<G2 as Group>::Base as Field>::ZERO;

@@ -431,7 +435,7 @@ None,

); let circuit1: NovaAugmentedCircuit<G2, TrivialTestCircuit<<G2 as Group>::Base>> = NovaAugmentedCircuit::new( - params1, + primary_params, Some(inputs1), TrivialTestCircuit::default(), ro_consts1,

@@ -453,16 +457,28 @@ None,

Some(inst1), None, ); - let circuit: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> = + let circuit2: NovaAugmentedCircuit<G1, TrivialTestCircuit<<G1 as Group>::Base>> = NovaAugmentedCircuit::new( - params2, + secondary_params, Some(inputs2), TrivialTestCircuit::default(), ro_consts2, ); - let _ = circuit.synthesize(&mut cs2); + let _ = circuit2.synthesize(&mut cs2); let (inst2, witness2) = cs2.r1cs_instance_and_witness(&shape2, &ck2).unwrap(); // Make sure that it is satisfiable 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, + ); } }
M src/gadgets/ecc.rs → src/gadgets/ecc.rs

@@ -975,16 +975,14 @@ }

#[test] 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 - 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 let mut cs: ShapeCS<G2> = ShapeCS::new();

@@ -1027,16 +1025,14 @@ }

#[test] 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 - 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 let mut cs: ShapeCS<G2> = ShapeCS::new();

@@ -1083,17 +1079,14 @@ }

#[test] 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 - 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 let mut cs: ShapeCS<G2> = ShapeCS::new();
M src/lib.rs → src/lib.rs

@@ -787,13 +787,16 @@ }

#[cfg(test)] mod tests { + use crate::provider::pedersen::CommitmentKeyExtTrait; + 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 core::marker::PhantomData; use ff::PrimeField;

@@ -848,15 +851,21 @@ vec![z[0] * z[0] * z[0] + z[0] + F::from(5u64)]

} } - #[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 let pp = PublicParams::< G1, G2, TrivialTestCircuit<<G1 as Group>::Scalar>, TrivialTestCircuit<<G2 as Group>::Scalar>, - >::setup(TrivialTestCircuit::default(), TrivialTestCircuit::default()); + >::setup(test_circuit1.clone(), test_circuit2.clone()); let num_steps = 1;

@@ -864,8 +873,8 @@ // produce a recursive SNARK

let res = RecursiveSNARK::prove_step( &pp, None, - TrivialTestCircuit::default(), - TrivialTestCircuit::default(), + test_circuit1, + test_circuit2, vec![<G1 as Group>::Scalar::ZERO], vec![<G2 as Group>::Scalar::ZERO], );

@@ -883,7 +892,17 @@ assert!(res.is_ok());

} #[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_secondary = CubicCircuit::default();

@@ -950,14 +969,30 @@ // sanity: check the claimed output with a direct computation of the same

assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]); let mut zn_secondary_direct = vec![<G2 as Group>::Scalar::ZERO]; 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, vec![<G2 as Group>::Scalar::from(2460515u64)]); } #[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_secondary = CubicCircuit::default();

@@ -1012,16 +1047,16 @@ // sanity: check the claimed output with a direct computation of the same

assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]); let mut zn_secondary_direct = vec![<G2 as Group>::Scalar::ZERO]; 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, vec![<G2 as Group>::Scalar::from(2460515u64)]); // 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 - 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()); let compressed_snark = res.unwrap();

@@ -1036,7 +1071,23 @@ assert!(res.is_ok());

} #[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_secondary = CubicCircuit::default();

@@ -1097,14 +1148,13 @@ assert_eq!(zn_secondary, zn_secondary_direct);

assert_eq!(zn_secondary, vec![<G2 as Group>::Scalar::from(2460515u64)]); // 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 - let (pk, vk) = CompressedSNARK::<_, _, _, _, S1Prime, S2Prime>::setup(&pp).unwrap(); + let (pk, vk) = CompressedSNARK::<_, _, _, _, S1Prime<G1>, S2Prime<G2>>::setup(&pp).unwrap(); // 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()); let compressed_snark = res.unwrap();

@@ -1119,7 +1169,23 @@ assert!(res.is_ok());

} #[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. #[derive(Clone, Debug)] struct FifthRootCheckingCircuit<F: PrimeField> {

@@ -1252,10 +1318,10 @@ let res = recursive_snark.verify(&pp, num_steps, z0_primary.clone(), z0_secondary.clone());

assert!(res.is_ok()); // 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 - 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()); let compressed_snark = res.unwrap();

@@ -1265,7 +1331,18 @@ assert!(res.is_ok());

} #[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 let pp = PublicParams::< G1,

@@ -1301,5 +1378,13 @@ let (zn_primary, zn_secondary) = res.unwrap();

assert_eq!(zn_primary, vec![<G1 as Group>::Scalar::ONE]); 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>(); } }
M src/nifs.rs → src/nifs.rs

@@ -162,8 +162,10 @@

Ok(()) } - #[test] - fn test_tiny_r1cs_bellperson() { + fn test_tiny_r1cs_bellperson_with<G>() + where + G: Group, + { use crate::bellperson::{ r1cs::{NovaShape, NovaWitness}, shape_cs::ShapeCS,

@@ -179,7 +181,7 @@ <<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants::new();

// Now get the instance and assignment for one instance 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(); // Make sure that the first instance is satisfiable

@@ -187,7 +189,7 @@ assert!(shape.is_sat(&ck, &U1, &W1).is_ok());

// Now get the instance and assignment for second instance 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(); // Make sure that the second instance is satisfiable

@@ -206,8 +208,13 @@ &W2,

); } + #[test] + fn test_tiny_r1cs_bellperson() { + test_tiny_r1cs_bellperson_with::<G>(); + } + #[allow(clippy::too_many_arguments)] - fn execute_sequence( + fn execute_sequence<G>( ck: &CommitmentKey<G>, ro_consts: &<<G as Group>::RO as ROTrait<<G as Group>::Base, <G as Group>::Scalar>>::Constants, pp_digest: &<G as Group>::Scalar,

@@ -216,7 +223,9 @@ U1: &R1CSInstance<G>,

W1: &R1CSWitness<G>, U2: &R1CSInstance<G>, W2: &R1CSWitness<G>, - ) { + ) where + G: Group, + { // produce a default running instance let mut r_W = RelaxedR1CSWitness::default(shape); let mut r_U = RelaxedR1CSInstance::default(ck, shape);
M src/provider/keccak.rs → src/provider/keccak.rs

@@ -101,10 +101,7 @@ };

use ff::PrimeField; 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"); // two scalars

@@ -134,6 +131,12 @@ assert_eq!(

hex::encode(c2.to_repr().as_ref()), "65f7908d53abcd18f3b1d767456ef9009b91c7566a635e9ca7be26e21d4d7a10" ); + } + + #[test] + fn test_keccak_transcript() { + type G = pasta_curves::pallas::Point; + test_keccak_transcript_with::<G>() } #[test]
M src/provider/poseidon.rs → src/provider/poseidon.rs

@@ -201,27 +201,31 @@

#[cfg(test)] mod tests { use super::*; - type S = pasta_curves::pallas::Scalar; - type B = pasta_curves::vesta::Scalar; - type G = pasta_curves::pallas::Point; use crate::{ 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 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 let mut csprng: OsRng = OsRng; - let constants = PoseidonConstantsCircuit::new(); + let constants = PoseidonConstantsCircuit::<G::Scalar>::new(); 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(); for i in 0..num_absorbs { - let num = S::random(&mut csprng); + let num = G::Scalar::random(&mut csprng); ro.absorb(num); let num_gadget = AllocatedNum::alloc(cs.namespace(|| format!("data {i}")), || Ok(num)).unwrap();

@@ -234,5 +238,12 @@ let num = ro.squeeze(NUM_CHALLENGE_BITS);

let num2_bits = ro_gadget.squeeze(&mut cs, NUM_CHALLENGE_BITS).unwrap(); let num2 = le_bits_to_num(&mut cs, num2_bits).unwrap(); 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>() } }
M src/spartan/pp.rs → src/spartan/pp.rs

@@ -2191,8 +2191,6 @@

#[cfg(test)] mod tests { use super::*; - type G = pasta_curves::pallas::Point; - type EE = crate::provider::ipa_pc::EvaluationEngine<G>; use ::bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError}; use core::marker::PhantomData; use ff::PrimeField;

@@ -2248,6 +2246,13 @@ }

#[test] 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(); // produce keys