diff --git a/Cargo.toml b/Cargo.toml index 50775ae56..a8f640f98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,6 @@ rayon-scan = "0.1.0" grumpkin-msm = { git = "https://github.com/lurk-lab/grumpkin-msm", branch = "dev" } [target.'cfg(target_arch = "wasm32")'.dependencies] -# see https://github.com/rust-random/rand/pull/948 getrandom = { version = "0.2.0", default-features = false, features = ["js"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/README.md b/README.md index 6ff01c56a..7edcab838 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,12 @@ A distinctive aspect of Nova is that it is the simplest recursive proof system i ## Details of the library This repository provides `nova-snark,` a Rust library implementation of Nova over a cycle of elliptic curves. Our code supports three curve cycles: (1) Pallas/Vesta, (2) BN254/Grumpkin, and (3) secp/secq. -At its core, Nova relies on a commitment scheme for vectors. Compressing IVC proofs using Spartan relies on interpreting commitments to vectors as commitments to multilinear polynomials and prove evaluations of committed polynomials. Our code implements two commitment schemes and evaluation arguments: +At its core, Nova relies on a commitment scheme for vectors. Compressing IVC proofs using Spartan relies on interpreting commitments to vectors as commitments to multilinear polynomials and prove evaluations of committed polynomials. Our code implements three commitment schemes and evaluation arguments: 1. Pedersen commitments with IPA-based evaluation argument (supported on all three curve cycles), and -2. Multilinear KZG commitments and evaluation argument (supported on curves with pairings e.g., BN254). +2. HyperKZG commitments and evaluation argument (supported on curves with pairings e.g., BN254). +3. KZG commitments with a [Zeromorph](https://eprint.iacr.org/2023/917) evaluation argument (supported on curves equipped with a pairing). -For more details on using multilinear KZG, please see the test `test_ivc_nontrivial_with_compression`. The multilinear KZG instantiation requires a universal trusted setup (the so-called "powers of tau"). In the `setup` method in `src/provider/mlkzg.rs`, one can load group elements produced in an existing KZG trusted setup (that was created for other proof systems based on univariate polynomials such as Plonk or variants), but the library does not currently do so (please see [this](https://github.com/microsoft/Nova/issues/270) issue). +For more details on using HyperKZG, please see the test `test_ivc_nontrivial_with_compression`. The HyperKZG instantiation requires a universal trusted setup (the so-called "powers of tau"). In the `setup` method in `src/provider/hyperkzg.rs`, one can load group elements produced in an existing KZG trusted setup (that was created for other proof systems based on univariate polynomials such as Plonk or variants), but the library does not currently do so (please see [this](https://github.com/microsoft/Nova/issues/270) issue). We also implement a SNARK, based on [Spartan](https://eprint.iacr.org/2019/550.pdf), to compress IVC proofs produced by Nova. There are two variants, one that does *not* use any preprocessing and another that uses preprocessing of circuits to ensure that the verifier's run time does not depend on the size of the step circuit. @@ -36,12 +37,14 @@ A front-end is a tool to take a high-level program and turn it into an intermedi In the future, we plan to support [Noir](https://noir-lang.org/), a Rust-like DSL and a compiler to transform those programs into an IR. See [this](https://github.com/microsoft/Nova/issues/275) GitHub issue for details. ## Tests and examples +By default, we enable the `asm` feature of an underlying library (which boosts performance by up to 50\%). If the library fails to build or run, one can pass `--no-default-features` to `cargo` commands noted below. + To run tests (we recommend the release mode to drastically shorten run times): ```text cargo test --release ``` -To run example: +To run an example: ```text cargo run --release --example minroot ``` diff --git a/benches/compressed-snark.rs b/benches/compressed-snark.rs index 9b806550d..5a900df3b 100644 --- a/benches/compressed-snark.rs +++ b/benches/compressed-snark.rs @@ -68,7 +68,8 @@ fn bench_compressed_snark_internal, S2: RelaxedR1C let c_secondary = TrivialCircuit::default(); // Produce public parameters - let pp = PublicParams::::setup(&c_primary, &c_secondary, &*S1::ck_floor(), &*S2::ck_floor()); + let pp = PublicParams::::setup(&c_primary, &c_secondary, &*S1::ck_floor(), &*S2::ck_floor()) + .unwrap(); // Produce prover and verifier keys for CompressedSNARK let (pk, vk) = CompressedSNARK::<_, S1, S2>::setup(&pp).unwrap(); diff --git a/benches/pcs.rs b/benches/pcs.rs index af12efcba..887985256 100644 --- a/benches/pcs.rs +++ b/benches/pcs.rs @@ -1,7 +1,8 @@ +use arecibo::provider::Bn256EngineIPA; use arecibo::provider::{ hyperkzg::EvaluationEngine as MLEvaluationEngine, ipa_pc::EvaluationEngine as IPAEvaluationEngine, non_hiding_zeromorph::ZMPCS, - shplonk::EvaluationEngine as Shplonk, Bn256Engine, Bn256EngineKZG, Bn256EngineZM, + shplonk::EvaluationEngine as Shplonk, Bn256EngineKZG, Bn256EngineZM, }; use arecibo::spartan::polys::multilinear::MultilinearPolynomial; use arecibo::traits::{ @@ -157,7 +158,7 @@ fn bench_pcs(c: &mut Criterion) { NUM_VARS_TEST_VECTOR, bench_pcs_proving_internal, bench_pcs_verifying_internal, - (ipa_assets, IPAEvaluationEngine), + (ipa_assets, IPAEvaluationEngine), (hyperkzg_assets, MLEvaluationEngine), (zm_assets, ZMPCS), (shplonk_assets, Shplonk) diff --git a/benches/recursive-snark.rs b/benches/recursive-snark.rs index dea0f1e24..d4437b549 100644 --- a/benches/recursive-snark.rs +++ b/benches/recursive-snark.rs @@ -76,7 +76,8 @@ fn bench_recursive_snark(c: &mut Criterion) { &c_secondary, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); // 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 22a19e2b0..9315ef40a 100644 --- a/benches/sha256.rs +++ b/benches/sha256.rs @@ -160,7 +160,8 @@ fn bench_recursive_snark(c: &mut Criterion) { &ttc, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let circuit_secondary = TrivialCircuit::default(); let z0_primary = vec![::Scalar::from(2u64)]; diff --git a/examples/and.rs b/examples/and.rs index 4622ddd0c..85b3b5577 100644 --- a/examples/and.rs +++ b/examples/and.rs @@ -230,7 +230,8 @@ fn main() { &circuit_secondary, &*S1::ck_floor(), &*S2::ck_floor(), - ); + ) + .unwrap(); println!("PublicParams::setup, took {:?} ", start.elapsed()); println!( @@ -290,7 +291,7 @@ fn main() { assert!(res.is_ok()); // produce a compressed SNARK - println!("Generating a CompressedSNARK using Spartan with multilinear KZG..."); + println!("Generating a CompressedSNARK using Spartan with HyperKZG..."); let (pk, vk) = CompressedSNARK::<_, S1, S2>::setup(&pp).unwrap(); let start = Instant::now(); diff --git a/examples/minroot.rs b/examples/minroot.rs index e443d1b29..d2e3d3668 100644 --- a/examples/minroot.rs +++ b/examples/minroot.rs @@ -227,7 +227,8 @@ fn main() { &circuit_secondary, &*S1::ck_floor(), &*S2::ck_floor(), - ); + ) + .unwrap(); println!("PublicParams::setup, took {:?} ", start.elapsed()); #[cfg(feature = "abomonate")] let pp = { @@ -334,7 +335,7 @@ fn main() { assert!(res.is_ok()); // produce a compressed SNARK - println!("Generating a CompressedSNARK using Spartan with multilinear KZG..."); + println!("Generating a CompressedSNARK using Spartan with HyperKZG..."); let (pk, vk) = CompressedSNARK::<_, S1, S2>::setup(&pp).unwrap(); let start = Instant::now(); diff --git a/src/bellpepper/mod.rs b/src/bellpepper/mod.rs index 6660c4dcd..a8a657e01 100644 --- a/src/bellpepper/mod.rs +++ b/src/bellpepper/mod.rs @@ -15,7 +15,7 @@ mod tests { shape_cs::ShapeCS, solver::SatisfyingAssignment, }, - provider::{Bn256Engine, PallasEngine, Secp256k1Engine}, + provider::{Bn256EngineKZG, PallasEngine, Secp256k1Engine}, traits::{snark::default_ck_hint, Engine}, }; use bellpepper_core::{num::AllocatedNum, ConstraintSystem}; @@ -59,7 +59,7 @@ mod tests { #[test] fn test_alloc_bit() { test_alloc_bit_with::(); - test_alloc_bit_with::(); + test_alloc_bit_with::(); test_alloc_bit_with::(); } } diff --git a/src/bellpepper/r1cs.rs b/src/bellpepper/r1cs.rs index facd8746e..ae0d5013f 100644 --- a/src/bellpepper/r1cs.rs +++ b/src/bellpepper/r1cs.rs @@ -117,17 +117,20 @@ fn add_constraint( assert_eq!(n + 1, C.indptr.len(), "C: invalid shape"); let add_constraint_component = |index: Index, coeff: &S, M: &mut SparseMatrix| { - match index { - Index::Input(idx) => { - // Inputs come last, with input 0, representing 'one', - // at position num_vars within the witness vector. - let idx = idx + num_vars; - M.data.push(*coeff); - M.indices.push(idx); - } - Index::Aux(idx) => { - M.data.push(*coeff); - M.indices.push(idx); + // we add constraints to the matrix only if the associated coefficient is non-zero + if *coeff != S::ZERO { + match index { + Index::Input(idx) => { + // Inputs come last, with input 0, representing 'one', + // at position num_vars within the witness vector. + let idx = idx + num_vars; + M.data.push(*coeff); + M.indices.push(idx); + } + Index::Aux(idx) => { + M.data.push(*coeff); + M.indices.push(idx); + } } } }; diff --git a/src/circuit.rs b/src/circuit.rs index 50f69db95..18be84383 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -372,7 +372,7 @@ mod tests { constants::{BN_LIMB_WIDTH, BN_N_LIMBS}, gadgets::utils::scalar_as_base, provider::{ - poseidon::PoseidonConstantsCircuit, Bn256Engine, GrumpkinEngine, PallasEngine, + poseidon::PoseidonConstantsCircuit, Bn256EngineKZG, GrumpkinEngine, PallasEngine, Secp256k1Engine, Secq256k1Engine, VestaEngine, }, traits::{circuit::TrivialCircuit, snark::default_ck_hint, CurveCycleEquipped, Dual}, @@ -468,13 +468,13 @@ mod tests { } #[test] - fn test_recursive_circuit_grumpkin() { + fn test_recursive_circuit_bn256_grumpkin() { 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 = PoseidonConstantsCircuit::default(); - let ro_consts2: ROConstantsCircuit = PoseidonConstantsCircuit::default(); + let ro_consts2: ROConstantsCircuit = PoseidonConstantsCircuit::default(); - test_recursive_circuit_with::( + test_recursive_circuit_with::( ¶ms1, ¶ms2, ro_consts1, @@ -485,7 +485,7 @@ mod tests { } #[test] - fn test_recursive_circuit_secp() { + fn test_recursive_circuit_secpq() { 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 = PoseidonConstantsCircuit::default(); diff --git a/src/errors.rs b/src/errors.rs index 9df15e137..3230ef9d5 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -9,9 +9,10 @@ pub enum NovaError { /// returned if the supplied row or col in (row,col,val) tuple is out of range #[error("InvalidIndex")] InvalidIndex, - /// returned if the supplied input is not even-sized - #[error("OddInputLength")] - OddInputLength, + /// returned if the step circuit calls inputize or alloc_io in its synthesize method + /// instead of passing output with the return value + #[error("InvalidStepCircuitIO")] + InvalidStepCircuitIO, /// returned if the supplied input is not of the right length #[error("InvalidInputLength")] InvalidInputLength, @@ -74,9 +75,9 @@ pub enum NovaError { /// Errors specific to the Polynomial commitment scheme #[derive(Debug, Eq, PartialEq, Error)] pub enum PCSError { - /// returned when an invalid inner product argument is provided - #[error("InvalidIPA")] - InvalidIPA, + /// returned when an invalid PCS evaluation argument is provided + #[error("InvalidPCS")] + InvalidPCS, /// returned when there is a Zeromorph error #[error("ZMError")] ZMError, diff --git a/src/gadgets/ecc.rs b/src/gadgets/ecc.rs index f7e9668a8..ec30572f2 100644 --- a/src/gadgets/ecc.rs +++ b/src/gadgets/ecc.rs @@ -785,7 +785,8 @@ mod tests { provider::{ bn256_grumpkin::{bn256, grumpkin}, secp_secq::{secp256k1, secq256k1}, - Bn256Engine, GrumpkinEngine, PallasEngine, Secp256k1Engine, Secq256k1Engine, VestaEngine, + Bn256EngineIPA, Bn256EngineKZG, GrumpkinEngine, PallasEngine, Secp256k1Engine, + Secq256k1Engine, VestaEngine, }, traits::{snark::default_ck_hint, Engine}, }; @@ -925,7 +926,7 @@ mod tests { test_ecc_ops_with::::GE>(); test_ecc_ops_with::::GE>(); - test_ecc_ops_with::::GE>(); + test_ecc_ops_with::::GE>(); test_ecc_ops_with::::GE>(); test_ecc_ops_with::::GE>(); @@ -1012,8 +1013,8 @@ mod tests { test_ecc_circuit_ops_with::(&expect!["2704"], &expect!["2692"]); test_ecc_circuit_ops_with::(&expect!["2704"], &expect!["2692"]); - test_ecc_circuit_ops_with::(&expect!["2738"], &expect!["2724"]); - test_ecc_circuit_ops_with::(&expect!["2738"], &expect!["2724"]); + test_ecc_circuit_ops_with::(&expect!["2738"], &expect!["2724"]); + test_ecc_circuit_ops_with::(&expect!["2738"], &expect!["2724"]); test_ecc_circuit_ops_with::( &expect!["2670"], @@ -1075,8 +1076,8 @@ mod tests { test_ecc_circuit_add_equal_with::(); test_ecc_circuit_add_equal_with::(); - test_ecc_circuit_add_equal_with::(); - test_ecc_circuit_add_equal_with::(); + test_ecc_circuit_add_equal_with::(); + test_ecc_circuit_add_equal_with::(); test_ecc_circuit_add_equal_with::(); test_ecc_circuit_add_equal_with::(); @@ -1135,11 +1136,11 @@ mod tests { test_ecc_circuit_add_negation_with::(&expect!["39"], &expect!["34"]); test_ecc_circuit_add_negation_with::(&expect!["39"], &expect!["34"]); - test_ecc_circuit_add_negation_with::( + test_ecc_circuit_add_negation_with::( &expect!["39"], &expect!["34"], ); - test_ecc_circuit_add_negation_with::( + test_ecc_circuit_add_negation_with::( &expect!["39"], &expect!["34"], ); diff --git a/src/lib.rs b/src/lib.rs index 01d2a9acd..3e6d02274 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -241,14 +241,14 @@ where /// let ck_hint1 = &*SPrime::::ck_floor(); /// let ck_hint2 = &*SPrime::::ck_floor(); /// - /// let pp = PublicParams::setup(&circuit1, &circuit2, ck_hint1, ck_hint2); + /// let pp = PublicParams::setup(&circuit1, &circuit2, ck_hint1, ck_hint2).unwrap(); /// ``` pub fn setup, C2: StepCircuit< as Engine>::Scalar>>( c_primary: &C1, c_secondary: &C2, ck_hint1: &CommitmentKeyHint, ck_hint2: &CommitmentKeyHint>, - ) -> Self { + ) -> Result { let augmented_circuit_params_primary = NovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, true); let augmented_circuit_params_secondary = @@ -276,7 +276,6 @@ where let _ = circuit_primary.synthesize(&mut cs); let (r1cs_shape_primary, ck_primary) = cs.r1cs_shape_and_key(ck_hint1); let ck_primary = Arc::new(ck_primary); - let circuit_shape_primary = R1CSWithArity::new(r1cs_shape_primary, F_arity_primary); // Initialize ck for the secondary let circuit_secondary: NovaAugmentedCircuit<'_, E1, C2> = NovaAugmentedCircuit::new( @@ -289,9 +288,15 @@ where let _ = circuit_secondary.synthesize(&mut cs); let (r1cs_shape_secondary, ck_secondary) = cs.r1cs_shape_and_key(ck_hint2); let ck_secondary = Arc::new(ck_secondary); + + if r1cs_shape_primary.num_io != 2 || r1cs_shape_secondary.num_io != 2 { + return Err(NovaError::InvalidStepCircuitIO); + } + + let circuit_shape_primary = R1CSWithArity::new(r1cs_shape_primary, F_arity_primary); let circuit_shape_secondary = R1CSWithArity::new(r1cs_shape_secondary, F_arity_secondary); - Self { + Ok(Self { F_arity_primary, F_arity_secondary, ro_consts_primary, @@ -305,7 +310,7 @@ where augmented_circuit_params_primary, augmented_circuit_params_secondary, digest: OnceCell::new(), - } + }) } /// Retrieve the digest of the public parameters. @@ -1017,7 +1022,7 @@ mod tests { use super::*; use crate::{ provider::{ - non_hiding_zeromorph::ZMPCS, Bn256Engine, Bn256EngineKZG, Bn256EngineZM, PallasEngine, + non_hiding_zeromorph::ZMPCS, Bn256EngineIPA, Bn256EngineKZG, Bn256EngineZM, PallasEngine, Secp256k1Engine, }, traits::{evaluation::EvaluationEngineTrait, snark::default_ck_hint}, @@ -1095,7 +1100,7 @@ mod tests { // this tests public parameters with a size specifically intended for a spark-compressed SNARK let ck_hint1 = &*SPrime::::ck_floor(); let ck_hint2 = &*SPrime::, EE2>::ck_floor(); - let pp = PublicParams::::setup(circuit1, circuit2, ck_hint1, ck_hint2); + let pp = PublicParams::::setup(circuit1, circuit2, ck_hint1, ck_hint2).unwrap(); let digest_str = pp .digest() @@ -1115,36 +1120,36 @@ mod tests { test_pp_digest_with::, EE<_>>( &TrivialCircuit::default(), &TrivialCircuit::default(), - &expect!["582db42439c0dcfc60d24b023ab83d81d97382ac2efa883c6f23147345efeb01"], + &expect!["e5a6a85b77f3fb958b69722a5a21bf656fd21a6b5a012708a4b086b6be6d2b03"], ); test_pp_digest_with::, EE<_>>( &CubicCircuit::default(), &TrivialCircuit::default(), - &expect!["83ef7f741c983bfc9193f1ba387b4966ca8d0818acac65583e30d72593b0f600"], + &expect!["ec707a8b822baebca114b6e61b238374f9ed358c542dd37ee73febb47832cd01"], ); - test_pp_digest_with::, EE<_>>( + test_pp_digest_with::, EE<_>>( &TrivialCircuit::default(), &TrivialCircuit::default(), - &expect!["09e1cc324b4469aec5abc55d48d8add5d161cbb70aa023f78e171c58e3199600"], + &expect!["df52de22456157eb056003d4dc580a167ab8ce40a151c9944ea09a6fd0028600"], ); - test_pp_digest_with::, EE<_>>( + test_pp_digest_with::, EE<_>>( &CubicCircuit::default(), &TrivialCircuit::default(), - &expect!["7602bf1fdf3d86b8a7228de4c163e11cc3908b93412548f8cf3ebc1bc638fd00"], + &expect!["b3ad0f4b734c5bd2ab9e83be8ee0cbaaa120e5cd0270b51cb9d7778a33f0b801"], ); test_pp_digest_with::, EE<_>>( &TrivialCircuit::default(), &TrivialCircuit::default(), - &expect!["dbbfd46ea48118694ec96631015c41cccc721c4f3aaf5b542bf18cca37878b02"], + &expect!["e1feca53664212ee750da857c726b2a09bb30b2964f22ea85a19b58c9eaf5701"], ); test_pp_digest_with::, EE<_>>( &CubicCircuit::default(), &TrivialCircuit::default(), - &expect!["c71fd5e574129205426e07edcb5fd0b26f78991d1ab883b1dfb7e82844480801"], + &expect!["4ad6b10b6fd24fecba49f08d35bc874a6da9c77735bc0bcf4b78b1914a97e602"], ); } @@ -1161,7 +1166,8 @@ mod tests { &test_circuit2, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 1; // produce a recursive SNARK @@ -1191,7 +1197,7 @@ mod tests { #[test] fn test_ivc_trivial() { test_ivc_trivial_with::(); - test_ivc_trivial_with::(); + test_ivc_trivial_with::(); test_ivc_trivial_with::(); } @@ -1208,7 +1214,8 @@ mod tests { &circuit_secondary, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 3; @@ -1263,7 +1270,7 @@ mod tests { #[test] fn test_ivc_nontrivial() { test_ivc_nontrivial_with::(); - test_ivc_nontrivial_with::(); + test_ivc_nontrivial_with::(); test_ivc_nontrivial_with::(); } @@ -1285,7 +1292,8 @@ mod tests { &circuit_secondary, &*S1::ck_floor(), &*S2::ck_floor(), - ); + ) + .unwrap(); let num_steps = 3; @@ -1362,7 +1370,7 @@ mod tests { #[test] fn test_ivc_nontrivial_with_compression() { test_ivc_nontrivial_with_compression_with::, EE<_>>(); - test_ivc_nontrivial_with_compression_with::, EE<_>>(); + test_ivc_nontrivial_with_compression_with::, EE<_>>(); test_ivc_nontrivial_with_compression_with::, EE<_>>(); test_ivc_nontrivial_with_compression_with::, EE<_>>(); test_ivc_nontrivial_with_compression_with::< @@ -1387,7 +1395,7 @@ mod tests { #[test] fn test_ivc_nontrivial_with_spark_compression() { test_ivc_nontrivial_with_spark_compression_with::, EE<_>>(); - test_ivc_nontrivial_with_spark_compression_with::, EE<_>>(); + test_ivc_nontrivial_with_spark_compression_with::, EE<_>>(); test_ivc_nontrivial_with_spark_compression_with::, EE<_>>(); test_ivc_nontrivial_with_spark_compression_with::, EE<_>>(); test_ivc_nontrivial_with_spark_compression_with::< @@ -1416,7 +1424,7 @@ mod tests { #[test] fn test_ivc_nontrivial_with_batched_compression() { test_ivc_nontrivial_with_batched_compression_with::, EE<_>>(); - test_ivc_nontrivial_with_batched_compression_with::, EE<_>>(); + test_ivc_nontrivial_with_batched_compression_with::, EE<_>>(); test_ivc_nontrivial_with_batched_compression_with::, EE<_>>(); test_ivc_nontrivial_with_batched_compression_with::, EE<_>>(); test_ivc_nontrivial_with_batched_compression_with::< @@ -1443,7 +1451,7 @@ mod tests { #[test] fn test_ivc_nontrivial_with_batched_spark_compression() { test_ivc_nontrivial_with_batched_spark_compression_with::, EE<_>>(); - test_ivc_nontrivial_with_batched_spark_compression_with::, EE<_>>(); + test_ivc_nontrivial_with_batched_spark_compression_with::, EE<_>>(); test_ivc_nontrivial_with_batched_spark_compression_with::, EE<_>>(); test_ivc_nontrivial_with_batched_spark_compression_with::, EE<_>>( ); @@ -1532,7 +1540,8 @@ mod tests { &circuit_secondary, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 3; @@ -1575,7 +1584,7 @@ mod tests { #[test] fn test_ivc_nondet_with_compression() { test_ivc_nondet_with_compression_with::, EE<_>>(); - test_ivc_nondet_with_compression_with::, EE<_>>(); + test_ivc_nondet_with_compression_with::, EE<_>>(); test_ivc_nondet_with_compression_with::, EE<_>>(); test_ivc_nondet_with_compression_with::, EE<_>>(); } @@ -1593,7 +1602,8 @@ mod tests { &test_circuit2, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 1; @@ -1630,7 +1640,68 @@ mod tests { #[test] fn test_ivc_base() { test_ivc_base_with::(); - test_ivc_base_with::(); + test_ivc_base_with::(); test_ivc_base_with::(); } + + fn test_setup_with() { + #[derive(Clone, Debug, Default)] + struct CircuitWithInputize { + _p: PhantomData, + } + + impl StepCircuit for CircuitWithInputize { + fn arity(&self) -> usize { + 1 + } + + fn synthesize>( + &self, + cs: &mut CS, + z: &[AllocatedNum], + ) -> Result>, SynthesisError> { + let x = &z[0]; + // a simplified version of this test would only have one input + // but beside the Nova Public parameter requirement for a num_io = 2, being + // probed in this test, we *also* require num_io to be even, so + // negative testing requires at least 4 inputs + let y = x.square(cs.namespace(|| "x_sq"))?; + y.inputize(cs.namespace(|| "y"))?; // inputize y + let y2 = x.square(cs.namespace(|| "x_sq2"))?; + y2.inputize(cs.namespace(|| "y2"))?; // inputize y2 + let y3 = x.square(cs.namespace(|| "x_sq3"))?; + y3.inputize(cs.namespace(|| "y3"))?; // inputize y2 + let y4 = x.square(cs.namespace(|| "x_sq4"))?; + y4.inputize(cs.namespace(|| "y4"))?; // inputize y2 + Ok(vec![y, y2, y3, y4]) + } + } + + // produce public parameters with trivial secondary + let circuit = CircuitWithInputize::<::Scalar>::default(); + let pp = PublicParams::::setup( + &circuit, + &TrivialCircuit::default(), + &*default_ck_hint(), + &*default_ck_hint(), + ); + assert!(pp.is_err()); + assert_eq!(pp.err(), Some(NovaError::InvalidStepCircuitIO)); + + // produce public parameters with the trivial primary + let circuit = CircuitWithInputize::< as Engine>::Scalar>::default(); + let pp = PublicParams::::setup( + &TrivialCircuit::default(), + &circuit, + &*default_ck_hint(), + &*default_ck_hint(), + ); + assert!(pp.is_err()); + assert_eq!(pp.err(), Some(NovaError::InvalidStepCircuitIO)); + } + + #[test] + fn test_setup() { + test_setup_with::(); + } } diff --git a/src/nifs.rs b/src/nifs.rs index 369a71f03..bfb4a8351 100644 --- a/src/nifs.rs +++ b/src/nifs.rs @@ -177,7 +177,7 @@ mod tests { solver::SatisfyingAssignment, test_shape_cs::TestShapeCS, }, - provider::{Bn256Engine, PallasEngine, Secp256k1Engine}, + provider::{Bn256EngineKZG, PallasEngine, Secp256k1Engine}, r1cs::{commitment_key, SparseMatrix}, traits::{snark::default_ck_hint, Engine}, }; @@ -258,7 +258,7 @@ mod tests { #[test] fn test_tiny_r1cs_bellpepper() { test_tiny_r1cs_bellpepper_with::(); - test_tiny_r1cs_bellpepper_with::(); + test_tiny_r1cs_bellpepper_with::(); test_tiny_r1cs_bellpepper_with::(); } @@ -441,7 +441,7 @@ mod tests { #[test] fn test_tiny_r1cs() { test_tiny_r1cs_with::(); - test_tiny_r1cs_with::(); + test_tiny_r1cs_with::(); test_tiny_r1cs_with::(); } } diff --git a/src/provider/hyperkzg.rs b/src/provider/hyperkzg.rs index a3a152d4d..15daf7f4f 100644 --- a/src/provider/hyperkzg.rs +++ b/src/provider/hyperkzg.rs @@ -418,10 +418,9 @@ where mod tests { use super::*; use crate::provider::util::test_utils::prove_verify_from_num_vars; - use crate::{ - provider::keccak::Keccak256Transcript, traits::commitment::CommitmentTrait, CommitmentKey, - }; + use crate::{provider::keccak::Keccak256Transcript, CommitmentKey}; use bincode::Options; + use expect_test::expect; type E = halo2curves::bn256::Bn256; type NE = crate::provider::Bn256EngineKZG; @@ -578,15 +577,12 @@ mod tests { // same state assert_eq!(post_c_p, post_c_v); - let my_options = bincode::DefaultOptions::new() + let proof_bytes = bincode::DefaultOptions::new() .with_big_endian() - .with_fixint_encoding(); - let mut output_bytes = my_options.serialize(&vk).unwrap(); - output_bytes.append(&mut my_options.serialize(&C.compress()).unwrap()); - output_bytes.append(&mut my_options.serialize(&point).unwrap()); - output_bytes.append(&mut my_options.serialize(&eval).unwrap()); - output_bytes.append(&mut my_options.serialize(&proof).unwrap()); - println!("total output = {} bytes", output_bytes.len()); + .with_fixint_encoding() + .serialize(&proof) + .unwrap(); + expect!["368"].assert_eq(&proof_bytes.len().to_string()); // Change the proof and expect verification to fail let mut bad_proof = proof.clone(); diff --git a/src/provider/ipa_pc.rs b/src/provider/ipa_pc.rs index e78c54ae1..b1bd24754 100644 --- a/src/provider/ipa_pc.rs +++ b/src/provider/ipa_pc.rs @@ -396,7 +396,7 @@ where if P_hat == CE::::commit(&ck_hat.combine(&ck_c), &[self.a_hat, self.a_hat * b_hat]) { Ok(()) } else { - Err(NovaError::PCSError(PCSError::InvalidIPA)) + Err(NovaError::PCSError(PCSError::InvalidPCS)) } } } diff --git a/src/provider/keccak.rs b/src/provider/keccak.rs index 081309481..44283e9cf 100644 --- a/src/provider/keccak.rs +++ b/src/provider/keccak.rs @@ -101,7 +101,7 @@ mod tests { use crate::{ provider::keccak::Keccak256Transcript, provider::{ - Bn256Engine, GrumpkinEngine, PallasEngine, Secp256k1Engine, Secq256k1Engine, VestaEngine, + Bn256EngineKZG, GrumpkinEngine, PallasEngine, Secp256k1Engine, Secq256k1Engine, VestaEngine, }, traits::{Engine, PrimeFieldExt, TranscriptEngineTrait, TranscriptReprTrait}, }; @@ -142,7 +142,7 @@ mod tests { "4d4bf42c065870395749fa1c4fb641df1e0d53f05309b03d5b1db7f0be3aa13d", ); - test_keccak_transcript_with::( + test_keccak_transcript_with::( "9fb71e3b74bfd0b60d97349849b895595779a240b92a6fae86bd2812692b6b0e", "bfd4c50b7d6317e9267d5d65c985eb455a3561129c0b3beef79bfc8461a84f18", ); @@ -246,7 +246,7 @@ mod tests { fn test_keccak_transcript_incremental_vs_explicit() { test_keccak_transcript_incremental_vs_explicit_with::(); test_keccak_transcript_incremental_vs_explicit_with::(); - test_keccak_transcript_incremental_vs_explicit_with::(); + test_keccak_transcript_incremental_vs_explicit_with::(); test_keccak_transcript_incremental_vs_explicit_with::(); test_keccak_transcript_incremental_vs_explicit_with::(); test_keccak_transcript_incremental_vs_explicit_with::(); diff --git a/src/provider/mod.rs b/src/provider/mod.rs index ae9494fec..87ca35203 100644 --- a/src/provider/mod.rs +++ b/src/provider/mod.rs @@ -35,15 +35,15 @@ use pasta_curves::{pallas, vesta}; use self::kzg_commitment::KZGCommitmentEngine; -/// An implementation of the Nova `Engine` trait with BN254 curve and Pedersen commitment scheme -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Bn256Engine; - /// An implementation of the Nova `Engine` trait with Grumpkin curve and Pedersen commitment scheme #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct GrumpkinEngine; -impl Engine for Bn256Engine { +/// An implementation of the Nova `Engine` trait with BN254 curve and Pedersen commitment scheme +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct Bn256EngineIPA; + +impl Engine for Bn256EngineIPA { type Base = bn256::Base; type Scalar = bn256::Scalar; type GE = bn256::Point; @@ -76,7 +76,7 @@ impl Engine for Bn256EngineZM { type TE = Keccak256Transcript; type CE = KZGCommitmentEngine; } -/// An implementation of Nova traits with multilinear KZG over the BN256 curve +/// An implementation of Nova traits with HyperKZG over the BN256 curve #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct Bn256EngineKZG; @@ -90,7 +90,7 @@ impl Engine for Bn256EngineKZG { type CE = KZGCommitmentEngine; } -impl CurveCycleEquipped for Bn256Engine { +impl CurveCycleEquipped for Bn256EngineIPA { type Secondary = GrumpkinEngine; } diff --git a/src/provider/poseidon.rs b/src/provider/poseidon.rs index 2a68dd3d9..8150f32f2 100644 --- a/src/provider/poseidon.rs +++ b/src/provider/poseidon.rs @@ -204,7 +204,7 @@ where mod tests { use super::*; use crate::provider::{ - Bn256Engine, GrumpkinEngine, PallasEngine, Secp256k1Engine, Secq256k1Engine, VestaEngine, + Bn256EngineKZG, GrumpkinEngine, PallasEngine, Secp256k1Engine, Secq256k1Engine, VestaEngine, }; use crate::{ bellpepper::solver::SatisfyingAssignment, constants::NUM_CHALLENGE_BITS, @@ -249,7 +249,7 @@ mod tests { fn test_poseidon_ro() { test_poseidon_ro_with::(); test_poseidon_ro_with::(); - test_poseidon_ro_with::(); + test_poseidon_ro_with::(); test_poseidon_ro_with::(); test_poseidon_ro_with::(); test_poseidon_ro_with::(); diff --git a/src/r1cs/mod.rs b/src/r1cs/mod.rs index caf336ecb..2efac6bcf 100644 --- a/src/r1cs/mod.rs +++ b/src/r1cs/mod.rs @@ -25,7 +25,7 @@ use rand_core::{CryptoRng, RngCore}; use rayon::prelude::*; use serde::{Deserialize, Serialize}; -pub(crate) use self::sparse::SparseMatrix; +pub(crate) use sparse::SparseMatrix; /// A type that holds the shape of the R1CS matrices #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Abomonation)] @@ -145,7 +145,7 @@ impl R1CSShape { // We require the number of public inputs/outputs to be even if num_io % 2 != 0 { - return Err(NovaError::OddInputLength); + return Err(NovaError::InvalidStepCircuitIO); } Ok(Self { @@ -827,7 +827,7 @@ mod tests { use super::*; use crate::{ - provider::{Bn256Engine, PallasEngine, Secp256k1Engine}, + provider::{Bn256EngineIPA, Bn256EngineKZG, PallasEngine, Secp256k1Engine}, r1cs::sparse::SparseMatrix, traits::Engine, }; @@ -910,7 +910,7 @@ mod tests { #[test] fn test_pad_tiny_r1cs() { test_pad_tiny_r1cs_with::(); - test_pad_tiny_r1cs_with::(); + test_pad_tiny_r1cs_with::(); test_pad_tiny_r1cs_with::(); } @@ -931,6 +931,6 @@ mod tests { #[test] fn test_random_r1cs() { - test_random_r1cs_with::(); + test_random_r1cs_with::(); } } diff --git a/src/supernova/circuit.rs b/src/supernova/circuit.rs index 0c8662056..6892a0943 100644 --- a/src/supernova/circuit.rs +++ b/src/supernova/circuit.rs @@ -714,7 +714,7 @@ mod tests { constants::{BN_LIMB_WIDTH, BN_N_LIMBS}, gadgets::utils::scalar_as_base, provider::{ - poseidon::PoseidonConstantsCircuit, Bn256Engine, GrumpkinEngine, PallasEngine, + poseidon::PoseidonConstantsCircuit, Bn256EngineIPA, GrumpkinEngine, PallasEngine, Secp256k1Engine, Secq256k1Engine, VestaEngine, }, supernova::circuit::TrivialTestCircuit, @@ -855,9 +855,9 @@ mod tests { let params1 = SuperNovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, true); let params2 = SuperNovaAugmentedCircuitParams::new(BN_LIMB_WIDTH, BN_N_LIMBS, false); let ro_consts1: ROConstantsCircuit = PoseidonConstantsCircuit::default(); - let ro_consts2: ROConstantsCircuit = PoseidonConstantsCircuit::default(); + let ro_consts2: ROConstantsCircuit = PoseidonConstantsCircuit::default(); - test_supernova_recursive_circuit_with::( + test_supernova_recursive_circuit_with::( ¶ms1, ¶ms2, ro_consts1, diff --git a/src/supernova/snark.rs b/src/supernova/snark.rs index 72b3c62cb..f6bdcbb14 100644 --- a/src/supernova/snark.rs +++ b/src/supernova/snark.rs @@ -282,7 +282,7 @@ fn field_as_usize(x: F) -> usize { mod test { use super::*; use crate::{ - provider::{ipa_pc, Bn256Engine, PallasEngine, Secp256k1Engine}, + provider::{ipa_pc, Bn256EngineIPA, PallasEngine, Secp256k1Engine}, spartan::{batched, batched_ppsnark, snark::RelaxedR1CSSNARK}, supernova::{circuit::TrivialSecondaryCircuit, NonUniformCircuit, StepCircuit}, }; @@ -513,11 +513,11 @@ mod test { fn test_nivc_trivial_with_compression() { // ppSNARK test_nivc_trivial_with_compression_with::, S2<_>>(); - test_nivc_trivial_with_compression_with::, S2<_>>(); + test_nivc_trivial_with_compression_with::, S2<_>>(); test_nivc_trivial_with_compression_with::, S2<_>>(); // classic SNARK test_nivc_trivial_with_compression_with::, S2<_>>(); - test_nivc_trivial_with_compression_with::, S2<_>>(); + test_nivc_trivial_with_compression_with::, S2<_>>(); test_nivc_trivial_with_compression_with::, S2<_>>(); } @@ -696,11 +696,11 @@ mod test { fn test_compression_with_circuit_size_difference() { // ppSNARK test_compression_with_circuit_size_difference_with::, S2<_>>(); - test_compression_with_circuit_size_difference_with::, S2<_>>(); + test_compression_with_circuit_size_difference_with::, S2<_>>(); test_compression_with_circuit_size_difference_with::, S2<_>>(); // classic SNARK test_compression_with_circuit_size_difference_with::, S2<_>>(); - test_compression_with_circuit_size_difference_with::, S2<_>>(); + test_compression_with_circuit_size_difference_with::, S2<_>>(); test_compression_with_circuit_size_difference_with::, S2<_>>(); } } diff --git a/src/supernova/test.rs b/src/supernova/test.rs index 62574c951..3adb7ce35 100644 --- a/src/supernova/test.rs +++ b/src/supernova/test.rs @@ -1,6 +1,6 @@ use crate::gadgets::utils::alloc_zero; use crate::provider::poseidon::PoseidonConstantsCircuit; -use crate::provider::Bn256Engine; +use crate::provider::Bn256EngineIPA; use crate::provider::PallasEngine; use crate::provider::Secp256k1Engine; use crate::provider::VestaEngine; @@ -606,18 +606,18 @@ fn test_supernova_pp_digest() { test_pp_digest_with::( &test_rom, - &expect!["2cd90507c9e6ae5e9afeec3dfd1544884436737d8c4f92abff0053c361fa6102"], + &expect!["698b3592bf271c0cc53245aee71ec3f8e0d16486b3efc73be290a0af27605b01"], ); let rom = vec![ OPCODE_1, OPCODE_1, OPCODE_0, OPCODE_0, OPCODE_1, OPCODE_1, OPCODE_0, OPCODE_0, OPCODE_1, OPCODE_1, ]; // Rom can be arbitrary length. - let test_rom_grumpkin = TestROM::::new(rom); + let test_rom_grumpkin = TestROM::::new(rom); - test_pp_digest_with::( + test_pp_digest_with::( &test_rom_grumpkin, - &expect!["c335819a49075ca959121d1dd016f944ee742c61122074be7a487ba814c40f00"], + &expect!["30418e576c11dd698054a6cc69d1b1e43ddf0f562abfb50b777147afad741a01"], ); let rom = vec![ @@ -628,7 +628,7 @@ fn test_supernova_pp_digest() { test_pp_digest_with::( &test_rom_secp, - &expect!["828b9e470907cb133898186d56a14e6644cd2005cb07dd6c7e947f32831b8c02"], + &expect!["c94ee4e2870e34d6d057aa66157f8315879ecf2692ab9d1e2567c5830bed1103"], ); } @@ -875,6 +875,6 @@ where #[test] fn test_nivc_nondet() { test_nivc_nondet_with::(); - test_nivc_nondet_with::(); + test_nivc_nondet_with::(); test_nivc_nondet_with::(); }