From 07d9b1e730ec511036180531c9e5cc99b54ea098 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?=
 <4142+huitseeker@users.noreply.github.com>
Date: Tue, 20 Feb 2024 08:45:51 -0500
Subject: [PATCH] Nova Forward ports (easy) (#329)

* update README; update version (#303)

* 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

* chore: update expect tests

* Improvements to error handling and naming (#309)

* rename and introduce checks about length

* introduce a test about public IO

* chore: remove needless annotation

---------

Co-authored-by: Srinath Setty <srinath@microsoft.com>
---
 Cargo.toml                  |   1 -
 README.md                   |  11 ++--
 benches/compressed-snark.rs |   3 +-
 benches/pcs.rs              |   5 +-
 benches/recursive-snark.rs  |   3 +-
 benches/sha256.rs           |   3 +-
 examples/and.rs             |   5 +-
 examples/minroot.rs         |   5 +-
 src/bellpepper/mod.rs       |   4 +-
 src/bellpepper/r1cs.rs      |  25 +++----
 src/circuit.rs              |  10 +--
 src/errors.rs               |  13 ++--
 src/gadgets/ecc.rs          |  17 ++---
 src/lib.rs                  | 127 ++++++++++++++++++++++++++++--------
 src/nifs.rs                 |   6 +-
 src/provider/hyperkzg.rs    |  18 ++---
 src/provider/ipa_pc.rs      |   2 +-
 src/provider/keccak.rs      |   6 +-
 src/provider/mod.rs         |  14 ++--
 src/provider/poseidon.rs    |   4 +-
 src/r1cs/mod.rs             |  10 +--
 src/supernova/circuit.rs    |   6 +-
 src/supernova/snark.rs      |  10 +--
 src/supernova/test.rs       |  14 ++--
 24 files changed, 201 insertions(+), 121 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 50775ae5..a8f640f9 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 6ff01c56..7edcab83 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 9b806550..5a900df3 100644
--- a/benches/compressed-snark.rs
+++ b/benches/compressed-snark.rs
@@ -68,7 +68,8 @@ fn bench_compressed_snark_internal<S1: RelaxedR1CSSNARKTrait<E1>, S2: RelaxedR1C
   let c_secondary = TrivialCircuit::default();
 
   // Produce public parameters
-  let pp = PublicParams::<E1>::setup(&c_primary, &c_secondary, &*S1::ck_floor(), &*S2::ck_floor());
+  let pp = PublicParams::<E1>::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 af12efcb..88798525 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<Bn256Engine>),
+    (ipa_assets, IPAEvaluationEngine<Bn256EngineIPA>),
     (hyperkzg_assets, MLEvaluationEngine<Bn256, Bn256EngineKZG>),
     (zm_assets, ZMPCS<Bn256, Bn256EngineZM>),
     (shplonk_assets, Shplonk<Bn256, Bn256EngineKZG>)
diff --git a/benches/recursive-snark.rs b/benches/recursive-snark.rs
index dea0f1e2..d4437b54 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 22a19e2b..9315ef40 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![<E1 as Engine>::Scalar::from(2u64)];
diff --git a/examples/and.rs b/examples/and.rs
index 4622ddd0..85b3b557 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 e443d1b2..d2e3d366 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 6660c4dc..a8a657e0 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::<PallasEngine>();
-    test_alloc_bit_with::<Bn256Engine>();
+    test_alloc_bit_with::<Bn256EngineKZG>();
     test_alloc_bit_with::<Secp256k1Engine>();
   }
 }
diff --git a/src/bellpepper/r1cs.rs b/src/bellpepper/r1cs.rs
index facd8746..ae0d5013 100644
--- a/src/bellpepper/r1cs.rs
+++ b/src/bellpepper/r1cs.rs
@@ -117,17 +117,20 @@ fn add_constraint<S: PrimeField>(
   assert_eq!(n + 1, C.indptr.len(), "C: invalid shape");
 
   let add_constraint_component = |index: Index, coeff: &S, M: &mut SparseMatrix<S>| {
-    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 50f69db9..18be8438 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<GrumpkinEngine> = PoseidonConstantsCircuit::default();
-    let ro_consts2: ROConstantsCircuit<Bn256Engine> = PoseidonConstantsCircuit::default();
+    let ro_consts2: ROConstantsCircuit<Bn256EngineKZG> = PoseidonConstantsCircuit::default();
 
-    test_recursive_circuit_with::<Bn256Engine>(
+    test_recursive_circuit_with::<Bn256EngineKZG>(
       &params1,
       &params2,
       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<Secq256k1Engine> = PoseidonConstantsCircuit::default();
diff --git a/src/errors.rs b/src/errors.rs
index 9df15e13..3230ef9d 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 f7e9668a..ec30572f 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::<pallas::Affine, <PallasEngine as Engine>::GE>();
     test_ecc_ops_with::<vesta::Affine, <VestaEngine as Engine>::GE>();
 
-    test_ecc_ops_with::<bn256::Affine, <Bn256Engine as Engine>::GE>();
+    test_ecc_ops_with::<bn256::Affine, <Bn256EngineIPA as Engine>::GE>();
     test_ecc_ops_with::<grumpkin::Affine, <GrumpkinEngine as Engine>::GE>();
 
     test_ecc_ops_with::<secp256k1::Affine, <Secp256k1Engine as Engine>::GE>();
@@ -1012,8 +1013,8 @@ mod tests {
     test_ecc_circuit_ops_with::<PallasEngine, VestaEngine>(&expect!["2704"], &expect!["2692"]);
     test_ecc_circuit_ops_with::<VestaEngine, PallasEngine>(&expect!["2704"], &expect!["2692"]);
 
-    test_ecc_circuit_ops_with::<Bn256Engine, GrumpkinEngine>(&expect!["2738"], &expect!["2724"]);
-    test_ecc_circuit_ops_with::<GrumpkinEngine, Bn256Engine>(&expect!["2738"], &expect!["2724"]);
+    test_ecc_circuit_ops_with::<Bn256EngineIPA, GrumpkinEngine>(&expect!["2738"], &expect!["2724"]);
+    test_ecc_circuit_ops_with::<GrumpkinEngine, Bn256EngineIPA>(&expect!["2738"], &expect!["2724"]);
 
     test_ecc_circuit_ops_with::<Secp256k1Engine, Secq256k1Engine>(
       &expect!["2670"],
@@ -1075,8 +1076,8 @@ mod tests {
     test_ecc_circuit_add_equal_with::<PallasEngine, VestaEngine>();
     test_ecc_circuit_add_equal_with::<VestaEngine, PallasEngine>();
 
-    test_ecc_circuit_add_equal_with::<Bn256Engine, GrumpkinEngine>();
-    test_ecc_circuit_add_equal_with::<GrumpkinEngine, Bn256Engine>();
+    test_ecc_circuit_add_equal_with::<Bn256EngineKZG, GrumpkinEngine>();
+    test_ecc_circuit_add_equal_with::<GrumpkinEngine, Bn256EngineKZG>();
 
     test_ecc_circuit_add_equal_with::<Secp256k1Engine, Secq256k1Engine>();
     test_ecc_circuit_add_equal_with::<Secq256k1Engine, Secp256k1Engine>();
@@ -1135,11 +1136,11 @@ mod tests {
     test_ecc_circuit_add_negation_with::<PallasEngine, VestaEngine>(&expect!["39"], &expect!["34"]);
     test_ecc_circuit_add_negation_with::<VestaEngine, PallasEngine>(&expect!["39"], &expect!["34"]);
 
-    test_ecc_circuit_add_negation_with::<Bn256Engine, GrumpkinEngine>(
+    test_ecc_circuit_add_negation_with::<Bn256EngineIPA, GrumpkinEngine>(
       &expect!["39"],
       &expect!["34"],
     );
-    test_ecc_circuit_add_negation_with::<GrumpkinEngine, Bn256Engine>(
+    test_ecc_circuit_add_negation_with::<GrumpkinEngine, Bn256EngineIPA>(
       &expect!["39"],
       &expect!["34"],
     );
diff --git a/src/lib.rs b/src/lib.rs
index 01d2a9ac..3e6d0227 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -241,14 +241,14 @@ where
   /// let ck_hint1 = &*SPrime::<E1>::ck_floor();
   /// let ck_hint2 = &*SPrime::<E2>::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<C1: StepCircuit<E1::Scalar>, C2: StepCircuit<<Dual<E1> as Engine>::Scalar>>(
     c_primary: &C1,
     c_secondary: &C2,
     ck_hint1: &CommitmentKeyHint<E1>,
     ck_hint2: &CommitmentKeyHint<Dual<E1>>,
-  ) -> Self {
+  ) -> Result<Self, NovaError> {
     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::<E1, EE1>::ck_floor();
     let ck_hint2 = &*SPrime::<Dual<E1>, EE2>::ck_floor();
-    let pp = PublicParams::<E1>::setup(circuit1, circuit2, ck_hint1, ck_hint2);
+    let pp = PublicParams::<E1>::setup(circuit1, circuit2, ck_hint1, ck_hint2).unwrap();
 
     let digest_str = pp
       .digest()
@@ -1115,36 +1120,36 @@ mod tests {
     test_pp_digest_with::<PallasEngine, _, _, EE<_>, EE<_>>(
       &TrivialCircuit::default(),
       &TrivialCircuit::default(),
-      &expect!["582db42439c0dcfc60d24b023ab83d81d97382ac2efa883c6f23147345efeb01"],
+      &expect!["e5a6a85b77f3fb958b69722a5a21bf656fd21a6b5a012708a4b086b6be6d2b03"],
     );
 
     test_pp_digest_with::<PallasEngine, _, _, EE<_>, EE<_>>(
       &CubicCircuit::default(),
       &TrivialCircuit::default(),
-      &expect!["83ef7f741c983bfc9193f1ba387b4966ca8d0818acac65583e30d72593b0f600"],
+      &expect!["ec707a8b822baebca114b6e61b238374f9ed358c542dd37ee73febb47832cd01"],
     );
 
-    test_pp_digest_with::<Bn256Engine, _, _, EE<_>, EE<_>>(
+    test_pp_digest_with::<Bn256EngineIPA, _, _, EE<_>, EE<_>>(
       &TrivialCircuit::default(),
       &TrivialCircuit::default(),
-      &expect!["09e1cc324b4469aec5abc55d48d8add5d161cbb70aa023f78e171c58e3199600"],
+      &expect!["df52de22456157eb056003d4dc580a167ab8ce40a151c9944ea09a6fd0028600"],
     );
 
-    test_pp_digest_with::<Bn256Engine, _, _, EE<_>, EE<_>>(
+    test_pp_digest_with::<Bn256EngineIPA, _, _, EE<_>, EE<_>>(
       &CubicCircuit::default(),
       &TrivialCircuit::default(),
-      &expect!["7602bf1fdf3d86b8a7228de4c163e11cc3908b93412548f8cf3ebc1bc638fd00"],
+      &expect!["b3ad0f4b734c5bd2ab9e83be8ee0cbaaa120e5cd0270b51cb9d7778a33f0b801"],
     );
 
     test_pp_digest_with::<Secp256k1Engine, _, _, EE<_>, EE<_>>(
       &TrivialCircuit::default(),
       &TrivialCircuit::default(),
-      &expect!["dbbfd46ea48118694ec96631015c41cccc721c4f3aaf5b542bf18cca37878b02"],
+      &expect!["e1feca53664212ee750da857c726b2a09bb30b2964f22ea85a19b58c9eaf5701"],
     );
     test_pp_digest_with::<Secp256k1Engine, _, _, EE<_>, 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::<PallasEngine>();
-    test_ivc_trivial_with::<Bn256Engine>();
+    test_ivc_trivial_with::<Bn256EngineIPA>();
     test_ivc_trivial_with::<Secp256k1Engine>();
   }
 
@@ -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::<PallasEngine>();
-    test_ivc_nontrivial_with::<Bn256Engine>();
+    test_ivc_nontrivial_with::<Bn256EngineKZG>();
     test_ivc_nontrivial_with::<Secp256k1Engine>();
   }
 
@@ -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::<PallasEngine, EE<_>, EE<_>>();
-    test_ivc_nontrivial_with_compression_with::<Bn256Engine, EE<_>, EE<_>>();
+    test_ivc_nontrivial_with_compression_with::<Bn256EngineIPA, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_compression_with::<Secp256k1Engine, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_compression_with::<Bn256EngineZM, ZMPCS<Bn256, _>, 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::<PallasEngine, EE<_>, EE<_>>();
-    test_ivc_nontrivial_with_spark_compression_with::<Bn256Engine, EE<_>, EE<_>>();
+    test_ivc_nontrivial_with_spark_compression_with::<Bn256EngineIPA, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_spark_compression_with::<Secp256k1Engine, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_spark_compression_with::<Bn256EngineZM, ZMPCS<Bn256, _>, 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::<PallasEngine, EE<_>, EE<_>>();
-    test_ivc_nontrivial_with_batched_compression_with::<Bn256Engine, EE<_>, EE<_>>();
+    test_ivc_nontrivial_with_batched_compression_with::<Bn256EngineIPA, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_batched_compression_with::<Secp256k1Engine, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_batched_compression_with::<Bn256EngineZM, ZMPCS<Bn256, _>, 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::<PallasEngine, EE<_>, EE<_>>();
-    test_ivc_nontrivial_with_batched_spark_compression_with::<Bn256Engine, EE<_>, EE<_>>();
+    test_ivc_nontrivial_with_batched_spark_compression_with::<Bn256EngineIPA, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_batched_spark_compression_with::<Secp256k1Engine, EE<_>, EE<_>>();
     test_ivc_nontrivial_with_batched_spark_compression_with::<Bn256EngineZM, ZMPCS<Bn256, _>, 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::<PallasEngine, EE<_>, EE<_>>();
-    test_ivc_nondet_with_compression_with::<Bn256Engine, EE<_>, EE<_>>();
+    test_ivc_nondet_with_compression_with::<Bn256EngineIPA, EE<_>, EE<_>>();
     test_ivc_nondet_with_compression_with::<Secp256k1Engine, EE<_>, EE<_>>();
     test_ivc_nondet_with_compression_with::<Bn256EngineZM, ZMPCS<Bn256, _>, 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::<PallasEngine>();
-    test_ivc_base_with::<Bn256Engine>();
+    test_ivc_base_with::<Bn256EngineKZG>();
     test_ivc_base_with::<Secp256k1Engine>();
   }
+
+  fn test_setup_with<E1: CurveCycleEquipped>() {
+    #[derive(Clone, Debug, Default)]
+    struct CircuitWithInputize<F: PrimeField> {
+      _p: PhantomData<F>,
+    }
+
+    impl<F: PrimeField> StepCircuit<F> for CircuitWithInputize<F> {
+      fn arity(&self) -> usize {
+        1
+      }
+
+      fn synthesize<CS: ConstraintSystem<F>>(
+        &self,
+        cs: &mut CS,
+        z: &[AllocatedNum<F>],
+      ) -> Result<Vec<AllocatedNum<F>>, 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::<<E1 as Engine>::Scalar>::default();
+    let pp = PublicParams::<E1>::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::<<Dual<E1> as Engine>::Scalar>::default();
+    let pp = PublicParams::<E1>::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::<Bn256EngineKZG>();
+  }
 }
diff --git a/src/nifs.rs b/src/nifs.rs
index 369a71f0..bfb4a835 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::<PallasEngine>();
-    test_tiny_r1cs_bellpepper_with::<Bn256Engine>();
+    test_tiny_r1cs_bellpepper_with::<Bn256EngineKZG>();
     test_tiny_r1cs_bellpepper_with::<Secp256k1Engine>();
   }
 
@@ -441,7 +441,7 @@ mod tests {
   #[test]
   fn test_tiny_r1cs() {
     test_tiny_r1cs_with::<PallasEngine>();
-    test_tiny_r1cs_with::<Bn256Engine>();
+    test_tiny_r1cs_with::<Bn256EngineKZG>();
     test_tiny_r1cs_with::<Secp256k1Engine>();
   }
 }
diff --git a/src/provider/hyperkzg.rs b/src/provider/hyperkzg.rs
index a3a152d4..15daf7f4 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 e78c54ae..b1bd2475 100644
--- a/src/provider/ipa_pc.rs
+++ b/src/provider/ipa_pc.rs
@@ -396,7 +396,7 @@ where
     if P_hat == CE::<E>::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 08130948..44283e9c 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::<Bn256Engine>(
+    test_keccak_transcript_with::<Bn256EngineKZG>(
       "9fb71e3b74bfd0b60d97349849b895595779a240b92a6fae86bd2812692b6b0e",
       "bfd4c50b7d6317e9267d5d65c985eb455a3561129c0b3beef79bfc8461a84f18",
     );
@@ -246,7 +246,7 @@ mod tests {
   fn test_keccak_transcript_incremental_vs_explicit() {
     test_keccak_transcript_incremental_vs_explicit_with::<PallasEngine>();
     test_keccak_transcript_incremental_vs_explicit_with::<VestaEngine>();
-    test_keccak_transcript_incremental_vs_explicit_with::<Bn256Engine>();
+    test_keccak_transcript_incremental_vs_explicit_with::<Bn256EngineKZG>();
     test_keccak_transcript_incremental_vs_explicit_with::<GrumpkinEngine>();
     test_keccak_transcript_incremental_vs_explicit_with::<Secp256k1Engine>();
     test_keccak_transcript_incremental_vs_explicit_with::<Secq256k1Engine>();
diff --git a/src/provider/mod.rs b/src/provider/mod.rs
index ae9494fe..87ca3520 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<Self>;
   type CE = KZGCommitmentEngine<Bn256>;
 }
-/// 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<Bn256>;
 }
 
-impl CurveCycleEquipped for Bn256Engine {
+impl CurveCycleEquipped for Bn256EngineIPA {
   type Secondary = GrumpkinEngine;
 }
 
diff --git a/src/provider/poseidon.rs b/src/provider/poseidon.rs
index 2a68dd3d..8150f32f 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::<PallasEngine>();
     test_poseidon_ro_with::<VestaEngine>();
-    test_poseidon_ro_with::<Bn256Engine>();
+    test_poseidon_ro_with::<Bn256EngineKZG>();
     test_poseidon_ro_with::<GrumpkinEngine>();
     test_poseidon_ro_with::<Secp256k1Engine>();
     test_poseidon_ro_with::<Secq256k1Engine>();
diff --git a/src/r1cs/mod.rs b/src/r1cs/mod.rs
index caf336ec..2efac6bc 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<E: Engine> R1CSShape<E> {
 
     // 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::<PallasEngine>();
-    test_pad_tiny_r1cs_with::<Bn256Engine>();
+    test_pad_tiny_r1cs_with::<Bn256EngineKZG>();
     test_pad_tiny_r1cs_with::<Secp256k1Engine>();
   }
 
@@ -931,6 +931,6 @@ mod tests {
 
   #[test]
   fn test_random_r1cs() {
-    test_random_r1cs_with::<Bn256Engine>();
+    test_random_r1cs_with::<Bn256EngineIPA>();
   }
 }
diff --git a/src/supernova/circuit.rs b/src/supernova/circuit.rs
index 0c866205..6892a094 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<GrumpkinEngine> = PoseidonConstantsCircuit::default();
-    let ro_consts2: ROConstantsCircuit<Bn256Engine> = PoseidonConstantsCircuit::default();
+    let ro_consts2: ROConstantsCircuit<Bn256EngineIPA> = PoseidonConstantsCircuit::default();
 
-    test_supernova_recursive_circuit_with::<Bn256Engine>(
+    test_supernova_recursive_circuit_with::<Bn256EngineIPA>(
       &params1,
       &params2,
       ro_consts1,
diff --git a/src/supernova/snark.rs b/src/supernova/snark.rs
index 72b3c62c..f6bdcbb1 100644
--- a/src/supernova/snark.rs
+++ b/src/supernova/snark.rs
@@ -282,7 +282,7 @@ fn field_as_usize<F: PrimeField>(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::<PallasEngine, S1PP<_>, S2<_>>();
-    test_nivc_trivial_with_compression_with::<Bn256Engine, S1PP<_>, S2<_>>();
+    test_nivc_trivial_with_compression_with::<Bn256EngineIPA, S1PP<_>, S2<_>>();
     test_nivc_trivial_with_compression_with::<Secp256k1Engine, S1PP<_>, S2<_>>();
     // classic SNARK
     test_nivc_trivial_with_compression_with::<PallasEngine, S1<_>, S2<_>>();
-    test_nivc_trivial_with_compression_with::<Bn256Engine, S1<_>, S2<_>>();
+    test_nivc_trivial_with_compression_with::<Bn256EngineIPA, S1<_>, S2<_>>();
     test_nivc_trivial_with_compression_with::<Secp256k1Engine, S1<_>, S2<_>>();
   }
 
@@ -696,11 +696,11 @@ mod test {
   fn test_compression_with_circuit_size_difference() {
     // ppSNARK
     test_compression_with_circuit_size_difference_with::<PallasEngine, S1PP<_>, S2<_>>();
-    test_compression_with_circuit_size_difference_with::<Bn256Engine, S1PP<_>, S2<_>>();
+    test_compression_with_circuit_size_difference_with::<Bn256EngineIPA, S1PP<_>, S2<_>>();
     test_compression_with_circuit_size_difference_with::<Secp256k1Engine, S1PP<_>, S2<_>>();
     // classic SNARK
     test_compression_with_circuit_size_difference_with::<PallasEngine, S1<_>, S2<_>>();
-    test_compression_with_circuit_size_difference_with::<Bn256Engine, S1<_>, S2<_>>();
+    test_compression_with_circuit_size_difference_with::<Bn256EngineIPA, S1<_>, S2<_>>();
     test_compression_with_circuit_size_difference_with::<Secp256k1Engine, S1<_>, S2<_>>();
   }
 }
diff --git a/src/supernova/test.rs b/src/supernova/test.rs
index 62574c95..3adb7ce3 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::<PallasEngine, _>(
     &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::<Bn256Engine>::new(rom);
+  let test_rom_grumpkin = TestROM::<Bn256EngineIPA>::new(rom);
 
-  test_pp_digest_with::<Bn256Engine, _>(
+  test_pp_digest_with::<Bn256EngineIPA, _>(
     &test_rom_grumpkin,
-    &expect!["c335819a49075ca959121d1dd016f944ee742c61122074be7a487ba814c40f00"],
+    &expect!["30418e576c11dd698054a6cc69d1b1e43ddf0f562abfb50b777147afad741a01"],
   );
 
   let rom = vec![
@@ -628,7 +628,7 @@ fn test_supernova_pp_digest() {
 
   test_pp_digest_with::<Secp256k1Engine, _>(
     &test_rom_secp,
-    &expect!["828b9e470907cb133898186d56a14e6644cd2005cb07dd6c7e947f32831b8c02"],
+    &expect!["c94ee4e2870e34d6d057aa66157f8315879ecf2692ab9d1e2567c5830bed1103"],
   );
 }
 
@@ -875,6 +875,6 @@ where
 #[test]
 fn test_nivc_nondet() {
   test_nivc_nondet_with::<PallasEngine>();
-  test_nivc_nondet_with::<Bn256Engine>();
+  test_nivc_nondet_with::<Bn256EngineIPA>();
   test_nivc_nondet_with::<Secp256k1Engine>();
 }