From e9442509c849bcf29d063b04321ced28bc1ad404 Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Wed, 31 Jan 2024 14:08:10 -0800 Subject: [PATCH 1/5] update README; update version (#303) --- README.md | 7 ++++--- examples/and.rs | 2 +- examples/minroot.rs | 2 +- src/provider/mod.rs | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6ff01c56a..50ca9d24b 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. diff --git a/examples/and.rs b/examples/and.rs index 4622ddd0c..375beca5e 100644 --- a/examples/and.rs +++ b/examples/and.rs @@ -290,7 +290,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..0a0a6e479 100644 --- a/examples/minroot.rs +++ b/examples/minroot.rs @@ -334,7 +334,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/provider/mod.rs b/src/provider/mod.rs index ae9494fec..1c7357a5b 100644 --- a/src/provider/mod.rs +++ b/src/provider/mod.rs @@ -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; From 0c4dc9bd5891228f835b83b4c202fe4cad32fd5b Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Wed, 7 Feb 2024 14:04:43 -0800 Subject: [PATCH 2/5] Miscellaneous improvements (details in commit messages) (#308) * move KZG engine to provider module; update paths everywhere * add a sparse matrix entry only if the coefficient is non-zero; update digests * move test code to place where it is used * move asm to default and add a note * update constants * update link * simplify test_pp_digest --- Cargo.toml | 1 - README.md | 4 +++- benches/pcs.rs | 5 +++-- src/bellpepper/mod.rs | 4 ++-- src/bellpepper/r1cs.rs | 25 ++++++++++++++----------- src/bellpepper/test_shape_cs.rs | 1 + src/circuit.rs | 10 +++++----- src/gadgets/ecc.rs | 17 +++++++++-------- src/lib.rs | 22 +++++++++++----------- src/nifs.rs | 6 +++--- src/provider/keccak.rs | 6 +++--- src/provider/mod.rs | 12 ++++++------ src/provider/poseidon.rs | 4 ++-- src/r1cs/mod.rs | 8 ++++---- src/supernova/circuit.rs | 6 +++--- src/supernova/snark.rs | 10 +++++----- src/supernova/test.rs | 8 ++++---- 17 files changed, 78 insertions(+), 71 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f1b115d41..521a45020 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 50ca9d24b..7edcab838 100644 --- a/README.md +++ b/README.md @@ -37,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/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/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/bellpepper/test_shape_cs.rs b/src/bellpepper/test_shape_cs.rs index 08c2d7eaf..31bc0d4bf 100644 --- a/src/bellpepper/test_shape_cs.rs +++ b/src/bellpepper/test_shape_cs.rs @@ -14,6 +14,7 @@ use ff::{Field, PrimeField}; #[derive(Clone, Copy)] struct OrderedVariable(Variable); +#[allow(unused)] #[derive(Debug)] enum NamedObject { Constraint(usize), 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/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..af9c48dac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1017,7 +1017,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}, @@ -1124,13 +1124,13 @@ mod tests { &expect!["83ef7f741c983bfc9193f1ba387b4966ca8d0818acac65583e30d72593b0f600"], ); - test_pp_digest_with::, EE<_>>( + test_pp_digest_with::, EE<_>>( &TrivialCircuit::default(), &TrivialCircuit::default(), &expect!["09e1cc324b4469aec5abc55d48d8add5d161cbb70aa023f78e171c58e3199600"], ); - test_pp_digest_with::, EE<_>>( + test_pp_digest_with::, EE<_>>( &CubicCircuit::default(), &TrivialCircuit::default(), &expect!["7602bf1fdf3d86b8a7228de4c163e11cc3908b93412548f8cf3ebc1bc638fd00"], @@ -1191,7 +1191,7 @@ mod tests { #[test] fn test_ivc_trivial() { test_ivc_trivial_with::(); - test_ivc_trivial_with::(); + test_ivc_trivial_with::(); test_ivc_trivial_with::(); } @@ -1263,7 +1263,7 @@ mod tests { #[test] fn test_ivc_nontrivial() { test_ivc_nontrivial_with::(); - test_ivc_nontrivial_with::(); + test_ivc_nontrivial_with::(); test_ivc_nontrivial_with::(); } @@ -1362,7 +1362,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 +1387,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 +1416,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 +1443,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<_>>( ); @@ -1575,7 +1575,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<_>>(); } @@ -1630,7 +1630,7 @@ mod tests { #[test] fn test_ivc_base() { test_ivc_base_with::(); - test_ivc_base_with::(); + test_ivc_base_with::(); test_ivc_base_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/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 1c7357a5b..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; @@ -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..23d5e5e4c 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)] @@ -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..1f8df4ecf 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; @@ -613,9 +613,9 @@ fn test_supernova_pp_digest() { 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"], ); @@ -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::(); } From 4c7bdff1c60050d01f332b65b89cfd36151b5db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Sat, 17 Feb 2024 09:35:22 -0500 Subject: [PATCH 3/5] chore: update expect tests --- src/lib.rs | 12 ++++++------ src/supernova/test.rs | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index af9c48dac..cf8d69f76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1115,36 +1115,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<_>>( &TrivialCircuit::default(), &TrivialCircuit::default(), - &expect!["09e1cc324b4469aec5abc55d48d8add5d161cbb70aa023f78e171c58e3199600"], + &expect!["df52de22456157eb056003d4dc580a167ab8ce40a151c9944ea09a6fd0028600"], ); 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"], ); } diff --git a/src/supernova/test.rs b/src/supernova/test.rs index 1f8df4ecf..3adb7ce35 100644 --- a/src/supernova/test.rs +++ b/src/supernova/test.rs @@ -606,7 +606,7 @@ fn test_supernova_pp_digest() { test_pp_digest_with::( &test_rom, - &expect!["2cd90507c9e6ae5e9afeec3dfd1544884436737d8c4f92abff0053c361fa6102"], + &expect!["698b3592bf271c0cc53245aee71ec3f8e0d16486b3efc73be290a0af27605b01"], ); let rom = vec![ @@ -617,7 +617,7 @@ fn test_supernova_pp_digest() { 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"], ); } From ac606984474592048bca68f6ee282c68262460e4 Mon Sep 17 00:00:00 2001 From: Srinath Setty Date: Thu, 15 Feb 2024 18:34:37 -0800 Subject: [PATCH 4/5] Improvements to error handling and naming (#309) * rename and introduce checks about length * introduce a test about public IO --- benches/compressed-snark.rs | 3 +- benches/recursive-snark.rs | 3 +- benches/sha256.rs | 3 +- examples/and.rs | 3 +- examples/minroot.rs | 3 +- src/errors.rs | 13 +++--- src/lib.rs | 93 ++++++++++++++++++++++++++++++++----- src/provider/hyperkzg.rs | 18 +++---- src/provider/ipa_pc.rs | 2 +- src/r1cs/mod.rs | 2 +- 10 files changed, 108 insertions(+), 35 deletions(-) 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/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 375beca5e..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!( diff --git a/examples/minroot.rs b/examples/minroot.rs index 0a0a6e479..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 = { 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/lib.rs b/src/lib.rs index cf8d69f76..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. @@ -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() @@ -1161,7 +1166,8 @@ mod tests { &test_circuit2, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 1; // produce a recursive SNARK @@ -1208,7 +1214,8 @@ mod tests { &circuit_secondary, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 3; @@ -1285,7 +1292,8 @@ mod tests { &circuit_secondary, &*S1::ck_floor(), &*S2::ck_floor(), - ); + ) + .unwrap(); let num_steps = 3; @@ -1532,7 +1540,8 @@ mod tests { &circuit_secondary, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 3; @@ -1593,7 +1602,8 @@ mod tests { &test_circuit2, &*default_ck_hint(), &*default_ck_hint(), - ); + ) + .unwrap(); let num_steps = 1; @@ -1633,4 +1643,65 @@ mod tests { 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/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/r1cs/mod.rs b/src/r1cs/mod.rs index 23d5e5e4c..2efac6bcf 100644 --- a/src/r1cs/mod.rs +++ b/src/r1cs/mod.rs @@ -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 { From 20ec1716e186d835bd9517c7b73e162277bebbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Mon, 19 Feb 2024 17:50:37 -0500 Subject: [PATCH 5/5] chore: remove needless annotation --- src/bellpepper/test_shape_cs.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bellpepper/test_shape_cs.rs b/src/bellpepper/test_shape_cs.rs index 31bc0d4bf..08c2d7eaf 100644 --- a/src/bellpepper/test_shape_cs.rs +++ b/src/bellpepper/test_shape_cs.rs @@ -14,7 +14,6 @@ use ff::{Field, PrimeField}; #[derive(Clone, Copy)] struct OrderedVariable(Variable); -#[allow(unused)] #[derive(Debug)] enum NamedObject { Constraint(usize),