diff --git a/benches/common/fib.rs b/benches/common/fib.rs index f32c1844b9..e9426bd32a 100644 --- a/benches/common/fib.rs +++ b/benches/common/fib.rs @@ -68,7 +68,7 @@ fn compute_coeffs(store: &Store) -> (usize, usize) { store.intern_empty_env(), store.cont_outermost(), ]; - let lang: Lang> = Lang::new(); + let lang: Lang = Lang::new(); let mut coef_lin = 0; let coef_ang; let step_func = eval_step(); diff --git a/benches/end2end.rs b/benches/end2end.rs index e6e5602edb..d201c08d82 100644 --- a/benches/end2end.rs +++ b/benches/end2end.rs @@ -59,7 +59,7 @@ fn end2end_benchmark(c: &mut Criterion) { let reduction_count = DEFAULT_REDUCTION_COUNT; // setup - let lang_pallas = Lang::>::new(); + let lang_pallas = Lang::::new(); let lang_pallas_rc = Arc::new(lang_pallas.clone()); let store = Store::default(); @@ -234,7 +234,7 @@ fn prove_benchmark(c: &mut Criterion) { let state = State::init_lurk_state().rccell(); - let lang_pallas = Lang::>::new(); + let lang_pallas = Lang::::new(); let lang_pallas_rc = Arc::new(lang_pallas.clone()); // use cached public params @@ -282,7 +282,7 @@ fn prove_compressed_benchmark(c: &mut Criterion) { let state = State::init_lurk_state().rccell(); - let lang_pallas = Lang::>::new(); + let lang_pallas = Lang::::new(); let lang_pallas_rc = Arc::new(lang_pallas.clone()); // use cached public params @@ -324,7 +324,7 @@ fn verify_benchmark(c: &mut Criterion) { let state = State::init_lurk_state().rccell(); - let lang_pallas = Lang::>::new(); + let lang_pallas = Lang::::new(); let lang_pallas_rc = Arc::new(lang_pallas.clone()); // use cached public params @@ -377,7 +377,7 @@ fn verify_compressed_benchmark(c: &mut Criterion) { let state = State::init_lurk_state().rccell(); - let lang_pallas = Lang::>::new(); + let lang_pallas = Lang::::new(); let lang_pallas_rc = Arc::new(lang_pallas.clone()); // use cached public params diff --git a/benches/fibonacci.rs b/benches/fibonacci.rs index 9cbd85c5b1..5cdac5a357 100644 --- a/benches/fibonacci.rs +++ b/benches/fibonacci.rs @@ -80,7 +80,7 @@ fn fibonacci_prove( c: &mut BenchmarkGroup<'_, M>, ) { let limit = fib_limit(prove_params.fib_n, prove_params.reduction_count); - let lang_pallas = Lang::>::new(); + let lang_pallas = Lang::::new(); let lang_rc = Arc::new(lang_pallas.clone()); // use cached public params diff --git a/benches/public_params.rs b/benches/public_params.rs index df52634ee9..9332a6c6b1 100644 --- a/benches/public_params.rs +++ b/benches/public_params.rs @@ -1,8 +1,5 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion, SamplingMode}; -use lurk::{ - eval::lang::{Coproc, Lang}, - proof::nova, -}; +use lurk::{eval::lang::Lang, proof::nova}; use std::sync::Arc; use std::time::Duration; @@ -14,8 +11,7 @@ const DEFAULT_REDUCTION_COUNT: usize = 10; fn public_params_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("public_params_benchmark"); group.sampling_mode(SamplingMode::Flat); - let lang_pallas = - Lang::>::new(); + let lang_pallas = Lang::::new(); let lang_pallas_rc = Arc::new(lang_pallas); let reduction_count = DEFAULT_REDUCTION_COUNT; diff --git a/benches/sha256.rs b/benches/sha256.rs index b8f6d55a0e..5ef0fce4a6 100644 --- a/benches/sha256.rs +++ b/benches/sha256.rs @@ -38,7 +38,7 @@ fn sha256_ivc( state: Rc>, arity: usize, n: usize, - input: &Vec, + input: &[usize], ) -> Ptr { assert_eq!(n, input.len()); let input = input @@ -128,7 +128,7 @@ fn sha256_ivc_prove( state.clone(), black_box(prove_params.arity), black_box(prove_params.n), - &(0..prove_params.n).collect(), + &(0..prove_params.n).collect::>(), ); let prover = NovaProver::new(prove_params.reduction_count, lang_rc.clone()); @@ -209,7 +209,7 @@ fn sha256_ivc_prove_compressed( state.clone(), black_box(prove_params.arity), black_box(prove_params.n), - &(0..prove_params.n).collect(), + &(0..prove_params.n).collect::>(), ); let prover = NovaProver::new(prove_params.reduction_count, lang_rc.clone()); @@ -293,7 +293,7 @@ fn sha256_nivc_prove( state.clone(), black_box(prove_params.arity), black_box(prove_params.n), - &(0..prove_params.n).collect(), + &(0..prove_params.n).collect::>(), ); let prover = SuperNovaProver::new(prove_params.reduction_count, lang_rc.clone()); diff --git a/benches/synthesis.rs b/benches/synthesis.rs index c130df7e4b..661038ec8f 100644 --- a/benches/synthesis.rs +++ b/benches/synthesis.rs @@ -40,7 +40,7 @@ fn synthesize( c: &mut BenchmarkGroup<'_, M>, ) { let limit = 1_000_000; - let lang_rc = Arc::new(Lang::>::new()); + let lang_rc = Arc::new(Lang::::new()); let state = State::init_lurk_state().rccell(); c.bench_with_input( diff --git a/examples/tp_table.rs b/examples/tp_table.rs index 73459290e8..588accd9e2 100644 --- a/examples/tp_table.rs +++ b/examples/tp_table.rs @@ -3,7 +3,7 @@ use ascii_table::{Align, AsciiTable}; use criterion::black_box; use lurk::{ eval::lang::{Coproc, Lang}, - lem::{eval::evaluate, multiframe::MultiFrame, store::Store}, + lem::{eval::evaluate, store::Store}, proof::nova::{public_params, NovaProver, PublicParams}, }; use num_traits::ToPrimitive; @@ -157,7 +157,7 @@ fn main() { let frames = evaluate::>(None, program, &store, limit).unwrap(); - let lang = Lang::>::new(); + let lang = Lang::::new(); let lang_arc = Arc::new(lang.clone()); let mut data = Vec::with_capacity(rc_vec.len()); @@ -166,8 +166,7 @@ fn main() { let prover: NovaProver<'_, _, _> = NovaProver::new(rc, lang_arc.clone()); println!("Getting public params for rc={rc}"); // TODO: use cache once it's fixed - let pp: PublicParams<_, MultiFrame<'_, _, Coproc>> = - public_params(rc, lang_arc.clone()); + let pp: PublicParams<_> = public_params(rc, lang_arc.clone()); let n_folds_data = (0..=max_n_folds) .map(|n_folds| { let n_frames = n_iters(n_folds, rc); diff --git a/src/cli/lurk_proof.rs b/src/cli/lurk_proof.rs index 1ccc37dea9..76cc2b7eeb 100644 --- a/src/cli/lurk_proof.rs +++ b/src/cli/lurk_proof.rs @@ -1,6 +1,6 @@ -use ::nova::traits::Engine; use abomonation::Abomonation; use anyhow::{bail, Result}; +use ff::PrimeField; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::{collections::HashMap, sync::Arc}; @@ -10,7 +10,7 @@ use crate::{ field::LurkField, lem::{pointers::ZPtr, store::Store}, proof::{ - nova::{self, CurveCycleEquipped, C1LEM, E1, E2}, + nova::{self, CurveCycleEquipped, Dual, C1LEM}, RecursiveSNARKTrait, }, public_parameters::{ @@ -154,9 +154,10 @@ impl<'a, F: CurveCycleEquipped + Serialize, C: Coprocessor + Serialize + Dese } impl< + 'a, F: CurveCycleEquipped + DeserializeOwned, - C: Coprocessor + Serialize + DeserializeOwned + 'static, - > LurkProof<'static, F, C> + C: Coprocessor + Serialize + DeserializeOwned + 'a, + > LurkProof<'a, F, C> { #[inline] pub(crate) fn is_cached(proof_key: &str) -> bool { @@ -165,12 +166,13 @@ impl< } impl< + 'a, F: CurveCycleEquipped + DeserializeOwned, - C: Coprocessor + Serialize + DeserializeOwned + 'static, - > LurkProof<'static, F, C> + C: Coprocessor + Serialize + DeserializeOwned + 'a, + > LurkProof<'a, F, C> where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + F::Repr: Abomonation, + as PrimeField>::Repr: Abomonation, { pub(crate) fn verify_proof(proof_key: &str) -> Result<()> { let lurk_proof = load::(&proof_path(proof_key))?; diff --git a/src/cli/repl/meta_cmd.rs b/src/cli/repl/meta_cmd.rs index 11e561ed9f..5c38f148b4 100644 --- a/src/cli/repl/meta_cmd.rs +++ b/src/cli/repl/meta_cmd.rs @@ -1,7 +1,8 @@ -use ::nova::traits::Engine; +use ::nova::supernova::StepCircuit; use abomonation::Abomonation; use anyhow::{anyhow, bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; +use ff::PrimeField; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::{collections::HashMap, process}; @@ -22,7 +23,7 @@ use crate::{ }, package::{Package, SymbolRef}, proof::{ - nova::{self, CurveCycleEquipped, C1LEM, E1, E2}, + nova::{self, CurveCycleEquipped, Dual, C1LEM}, RecursiveSNARKTrait, }, public_parameters::{ @@ -44,12 +45,13 @@ pub(super) struct MetaCmd + Serialize + Deserial } impl< + 'a, F: CurveCycleEquipped + Serialize + DeserializeOwned, C: Coprocessor + Serialize + DeserializeOwned + 'static, > MetaCmd where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + F::Repr: Abomonation, + as PrimeField>::Repr: Abomonation, { const LOAD: MetaCmd = MetaCmd { name: "load", @@ -992,7 +994,7 @@ where let (fun, proto_rc) = Self::get_fun_and_rc(repl, ptcl)?; - match load::>(&path)? { + match load::>>(&path)? { ProtocolProof::Nova { args: LurkData { z_ptr, z_dag }, proof, @@ -1096,23 +1098,14 @@ fn get_path + Serialize + DeserializeOwned>( #[non_exhaustive] #[derive(Serialize, Deserialize)] #[serde(bound(serialize = "F: Serialize", deserialize = "F: DeserializeOwned"))] -enum ProtocolProof<'a, F: CurveCycleEquipped, C: Coprocessor + Serialize + DeserializeOwned> -where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, -{ +enum ProtocolProof { Nova { args: LurkData, - proof: nova::Proof>, + proof: nova::Proof, }, } -impl<'a, F: CurveCycleEquipped, C: Coprocessor + 'a + Serialize + DeserializeOwned> - HasFieldModulus for ProtocolProof<'a, F, C> -where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, -{ +impl> HasFieldModulus for ProtocolProof { fn field_modulus() -> String { F::MODULUS.to_owned() } diff --git a/src/cli/repl/mod.rs b/src/cli/repl/mod.rs index 7d2a72e76c..bb55493174 100644 --- a/src/cli/repl/mod.rs +++ b/src/cli/repl/mod.rs @@ -3,7 +3,7 @@ mod meta_cmd; use abomonation::Abomonation; use anyhow::{anyhow, bail, Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; -use nova::traits::Engine; +use ff::PrimeField; use rustyline::{ error::ReadlineError, history::DefaultHistory, @@ -39,7 +39,7 @@ use crate::{ }, parser, proof::{ - nova::{CurveCycleEquipped, NovaProver, E1, E2}, + nova::{CurveCycleEquipped, Dual, NovaProver}, RecursiveSNARKTrait, }, public_parameters::{ @@ -166,8 +166,8 @@ impl< C: Coprocessor + Serialize + DeserializeOwned + 'static, > Repl where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + F::Repr: Abomonation, + as PrimeField>::Repr: Abomonation, { pub(crate) fn new( store: Store, diff --git a/src/eval/lang.rs b/src/eval/lang.rs index 43ae0d0a58..0ad5f6ca65 100644 --- a/src/eval/lang.rs +++ b/src/eval/lang.rs @@ -73,7 +73,7 @@ pub enum Coproc { /// // TODO: Define a trait for the Hash and parameterize on that also. #[derive(Debug, Default, Clone, Deserialize, Serialize)] -pub struct Lang { +pub struct Lang> { /// An IndexMap that stores coprocessors with their associated `Sym` keys. coprocessors: IndexMap, _p: PhantomData, @@ -185,12 +185,12 @@ pub(crate) mod test { #[test] fn lang() { - Lang::>::new(); + Lang::::new(); } #[test] fn dummy_lang() { - let _lang = Lang::>::new_with_bindings(vec![( + let _lang = Lang::::new_with_bindings(vec![( sym!("coproc", "dummy"), DummyCoprocessor::new().into(), )]); diff --git a/src/lem/eval.rs b/src/lem/eval.rs index 6631b153ad..135ebf0731 100644 --- a/src/lem/eval.rs +++ b/src/lem/eval.rs @@ -1720,10 +1720,7 @@ fn make_thunk() -> Func { #[cfg(test)] mod tests { use super::*; - use crate::{ - eval::lang::{Coproc, Lang}, - lem::store::Store, - }; + use crate::{eval::lang::Lang, lem::store::Store}; use bellpepper_core::{test_cs::TestConstraintSystem, Comparable}; use expect_test::{expect, Expect}; use halo2curves::bn256::Fr; @@ -1734,7 +1731,7 @@ mod tests { let func = eval_step(); let frame = Frame::blank(func, 0, &store); let mut cs = TestConstraintSystem::::new(); - let lang: Lang> = Lang::new(); + let lang: Lang = Lang::new(); let _ = func.synthesize_frame_aux(&mut cs, &store, &frame, &lang); let expect_eq = |computed: usize, expected: Expect| { expected.assert_eq(&computed.to_string()); diff --git a/src/lem/multiframe.rs b/src/lem/multiframe.rs index 9fc1cfe5f9..e269fb09fa 100644 --- a/src/lem/multiframe.rs +++ b/src/lem/multiframe.rs @@ -15,7 +15,7 @@ use crate::{ eval::lang::Lang, field::{LanguageField, LurkField}, proof::{ - nova::{CurveCycleEquipped, E1, E2}, + nova::{CurveCycleEquipped, E1}, supernova::{FoldingConfig, C2}, CEKState, EvaluationStore, FrameLike, Provable, }, @@ -898,11 +898,14 @@ impl<'a, F: LurkField, C: Coprocessor> nova::supernova::StepCircuit for Mu } } -impl<'a, F, C> NonUniformCircuit, E2, MultiFrame<'a, F, C>, C2> for MultiFrame<'a, F, C> +impl<'a, F, C> NonUniformCircuit> for MultiFrame<'a, F, C> where F: CurveCycleEquipped + LurkField, C: Coprocessor + 'a, { + type C1 = MultiFrame<'a, F, C>; + type C2 = C2; + fn num_circuits(&self) -> usize { assert_eq!(self.pc, 0); self.get_lang().coprocessor_count() + 1 @@ -1042,7 +1045,7 @@ mod tests { let mut cs_clone = cs.clone(); - let lang = Lang::>::new(); + let lang = Lang::::new(); let output_sequential = synthesize_frames_sequential( &mut cs, @@ -1083,7 +1086,7 @@ mod tests { // not self-evaluating let expr = store.read_with_default_state("(+ 1 2)").unwrap(); - let lang = Arc::new(Lang::>::new()); + let lang = Arc::new(Lang::::new()); let mut frames = evaluate::>(None, expr, &store, 1).unwrap(); assert_eq!(frames.len(), 1); diff --git a/src/lem/tests/eval_tests.rs b/src/lem/tests/eval_tests.rs index ed19de2a10..0b3e39c393 100644 --- a/src/lem/tests/eval_tests.rs +++ b/src/lem/tests/eval_tests.rs @@ -87,7 +87,7 @@ fn do_test_aux>( lang, ) } else { - let lang = Lang::>::new(); + let lang = Lang::::new(); do_test( s, ptr, diff --git a/src/proof/mod.rs b/src/proof/mod.rs index 86cdf7a0a6..549aa53429 100644 --- a/src/proof/mod.rs +++ b/src/proof/mod.rs @@ -15,7 +15,7 @@ pub mod supernova; #[cfg(test)] mod tests; -use ::nova::traits::Engine; +use ff::Field; use std::sync::Arc; use crate::{ @@ -24,7 +24,7 @@ use crate::{ eval::lang::Lang, field::LurkField, lem::{eval::EvalConfig, pointers::Ptr, store::Store}, - proof::nova::E2, + proof::nova::Dual, }; use self::{nova::CurveCycleEquipped, supernova::FoldingConfig}; @@ -111,9 +111,8 @@ where /// Return the `z0_secondary` #[inline] - fn z0_secondary() -> Vec<::Scalar> { - use ff::Field; - vec![ as Engine>::Scalar::ZERO] + fn z0_secondary() -> Vec> { + vec![Dual::::ZERO] } } diff --git a/src/proof/nova.rs b/src/proof/nova.rs index 0e5c887d77..88d78a5a84 100644 --- a/src/proof/nova.rs +++ b/src/proof/nova.rs @@ -2,12 +2,12 @@ use bellpepper_core::{num::AllocatedNum, ConstraintSystem}; use halo2curves::bn256::Fr as Bn256Scalar; use nova::{ errors::NovaError, - provider::{Bn256Engine, GrumpkinEngine, PallasEngine, VestaEngine}, + provider::{Bn256Engine, PallasEngine}, traits::{ circuit::{StepCircuit, TrivialCircuit}, evaluation::EvaluationEngineTrait, snark::RelaxedR1CSSNARKTrait, - Engine, + CurveCycleEquipped as NovaCurveCycleEquipped, Dual as DualEng, Engine, }, CompressedSNARK, ProverKey, R1CSWithArity, RecursiveSNARK, VerifierKey, }; @@ -43,40 +43,39 @@ pub trait CurveCycleEquipped: LurkField { /// /// The following abstracts over curve cycle groups for which there exists an implementation of [`nova::traits::evaluation::EvaluationEngineTrait`], /// encapsulating these idiosyncracies within Nova. + type E1: NovaCurveCycleEquipped; /// a concrete implementation of an [`nova::traits::evaluation::EvaluationEngineTrait`] for G1, type EE1: EvaluationEngineTrait; /// a concrete implementation of an [`nova::traits::evaluation::EvaluationEngineTrait`] for G2, - type EE2: EvaluationEngineTrait; - - /// The group type for the first curve in the cycle. - type E1: Engine::Scalar, Scalar = Self>; - /// The group type for the second curve in the cycle. - type E2: Engine::Scalar>; + type EE2: EvaluationEngineTrait>; } impl CurveCycleEquipped for pallas::Scalar { - type EE1 = nova::provider::ipa_pc::EvaluationEngine; - type EE2 = nova::provider::ipa_pc::EvaluationEngine; - type E1 = PallasEngine; - type E2 = VestaEngine; + + type EE1 = nova::provider::ipa_pc::EvaluationEngine; + type EE2 = nova::provider::ipa_pc::EvaluationEngine>; } // The impl CurveCycleEquipped for vesta::Scalar is academically possible, but voluntarily omitted to avoid confusion. impl CurveCycleEquipped for Bn256Scalar { type EE1 = nova::provider::ipa_pc::EvaluationEngine; - type EE2 = nova::provider::ipa_pc::EvaluationEngine; + type EE2 = nova::provider::ipa_pc::EvaluationEngine>; type E1 = Bn256Engine; - type E2 = GrumpkinEngine; } // The impl CurveCycleEquipped for grumpkin::Scalar is academically possible, but voluntarily omitted to avoid confusion. /// Convenience alias for the primary group type pegged to a LurkField through a CurveCycleEquipped type. pub type E1 = ::E1; -/// Convenience alias for the secondary group type pegged to a LurkField through a CurveCycleEquipped type. -pub type E2 = ::E2; + +/// Convenience alias for the Dual field of a CurveCycleEquipped field. +/// By definition, this is both: +/// - the Base field for the associated Primary Engine, +/// - the Scalar field for the Secondary Engine. +pub type Dual = + <<::E1 as NovaCurveCycleEquipped>::Secondary as Engine>::Scalar; /// Type alias for the Evaluation Engine using G1 group elements. pub type EE1 = ::EE1; @@ -90,42 +89,40 @@ pub type SS1 = nova::spartan::snark::RelaxedR1CSSNARK, EE1>; /// Type alias for the Relaxed R1CS Spartan SNARK using G2 group elements, EE2. // NOTE: this is not a SNARK that uses computational commitments, // that SNARK would be found at nova::spartan::ppsnark::RelaxedR1CSSNARK, -pub type SS2 = nova::spartan::snark::RelaxedR1CSSNARK, EE2>; +pub type SS2 = nova::spartan::snark::RelaxedR1CSSNARK>, EE2>; /// Type alias for a MultiFrame with S1 field elements. /// This uses the <::G1 as Group>::Scalar type for the G1 scalar field elements /// to reflect it this should not be used outside the Nova context pub type C1LEM<'a, F, C> = crate::lem::multiframe::MultiFrame<'a, F, C>; /// Type alias for a Trivial Test Circuit with G2 scalar field elements. -pub type C2 = TrivialCircuit< as Engine>::Scalar>; +pub type C2 = TrivialCircuit>; /// Type alias for Nova Circuit Parameters with the curve cycle types defined above. pub type NovaCircuitShape = R1CSWithArity>; /// Type alias for Nova Public Parameters with the curve cycle types defined above. -pub type NovaPublicParams = nova::PublicParams, E2, C1, C2>; +pub type NovaPublicParams = nova::PublicParams>; /// A struct that contains public parameters for the Nova proving system. #[derive(Serialize, Deserialize)] #[serde(bound = "")] -pub struct PublicParams> +pub struct PublicParams where F: CurveCycleEquipped, { /// Public parameters for the Nova proving system. - pub pp: NovaPublicParams, + pub pp: NovaPublicParams, /// Prover and verifier key for final proof compression #[serde(skip)] pk_and_vk: OnceCell<( - ProverKey, E2, SC, C2, SS1, SS2>, - VerifierKey, E2, SC, C2, SS1, SS2>, + ProverKey, SS1, SS2>, + VerifierKey, SS1, SS2>, )>, } // this avoids dipping into the pk/vk -impl + std::fmt::Debug> std::fmt::Debug - for PublicParams -{ +impl std::fmt::Debug for PublicParams { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("PublicParams") .field("pp", &self.pp) @@ -133,28 +130,26 @@ impl + std::fmt::Debug> std::fmt::Debu } } -impl> PublicParams { +impl PublicParams { /// provides a reference to a ProverKey suitable for producing a CompressedProof - pub fn pk(&self) -> &ProverKey, E2, SC, C2, SS1, SS2> { - let (pk, _vk) = self.pk_and_vk.get_or_init(|| { - CompressedSNARK::, E2, SC, C2, SS1, SS2>::setup(&self.pp).unwrap() - }); + pub fn pk(&self) -> &ProverKey, SS1, SS2> { + let (pk, _vk) = self + .pk_and_vk + .get_or_init(|| CompressedSNARK::, SS1, SS2>::setup(&self.pp).unwrap()); pk } /// provides a reference to a VerifierKey suitable for verifying a CompressedProof - pub fn vk(&self) -> &VerifierKey, E2, SC, C2, SS1, SS2> { - let (_pk, vk) = self.pk_and_vk.get_or_init(|| { - CompressedSNARK::, E2, SC, C2, SS1, SS2>::setup(&self.pp).unwrap() - }); + pub fn vk(&self) -> &VerifierKey, SS1, SS2> { + let (_pk, vk) = self + .pk_and_vk + .get_or_init(|| CompressedSNARK::, SS1, SS2>::setup(&self.pp).unwrap()); vk } } -impl> From> - for PublicParams -{ - fn from(pp: NovaPublicParams) -> PublicParams { +impl From> for PublicParams { + fn from(pp: NovaPublicParams) -> PublicParams { PublicParams { pp, pk_and_vk: OnceCell::new(), @@ -165,15 +160,16 @@ impl> From> /// An enum representing the two types of proofs that can be generated and verified. #[derive(Serialize, Deserialize)] #[serde(bound = "")] -pub enum Proof> { +pub enum Proof { /// A proof for the intermediate steps of a recursive computation along with /// the number of steps used for verification - Recursive(Box, E2, C1, C2>>, usize), + Recursive(Box>>, usize, PhantomData), /// A proof for the final step of a recursive computation along with the number /// of steps used for verification Compressed( - Box, E2, C1, C2, SS1, SS2>>, + Box, SS1, SS2>>, usize, + PhantomData, ), } @@ -189,18 +185,18 @@ pub fn circuit_cache_key<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( ) -> F { let folding_config = Arc::new(FoldingConfig::new_ivc(lang, 2)); let circuit = C1LEM::<'a, F, C>::blank(folding_config, 0); - F::from(rc as u64) * nova::circuit_digest::(&circuit) + F::from(rc as u64) * nova::circuit_digest::(&circuit) } /// Generates the public parameters for the Nova proving system. pub fn public_params<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( reduction_count: usize, lang: Arc>, -) -> PublicParams> { +) -> PublicParams { let (circuit_primary, circuit_secondary) = circuits(reduction_count, lang); let commitment_size_hint1 = as RelaxedR1CSSNARKTrait>>::ck_floor(); - let commitment_size_hint2 = as RelaxedR1CSSNARKTrait>>::ck_floor(); + let commitment_size_hint2 = as RelaxedR1CSSNARKTrait>>>::ck_floor(); let pp = nova::PublicParams::setup( &circuit_primary, @@ -229,13 +225,13 @@ pub fn circuits<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait> for Proof> { - type PublicParams = PublicParams>; + type PublicParams = PublicParams; type ErrorType = NovaError; #[tracing::instrument(skip_all, name = "nova::prove_recursively")] fn prove_recursively( - pp: &PublicParams>, + pp: &PublicParams, z0: &[F], steps: Vec>, store: &Store, @@ -252,8 +248,7 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait, E2, C1LEM<'a, F, C>, C2>> = - None; + let mut recursive_snark: Option>> = None; // the shadowing here is voluntary let recursive_snark = if lurk_config(None, None) @@ -282,7 +277,7 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait> RecursiveSNARKTrait> RecursiveSNARKTrait as Engine>::Scalar>::new(); + let mut cs = TestConstraintSystem::::new(); let zi = store.to_scalar_vector(circuit_primary.input()); let zi_allocated: Vec<_> = zi @@ -339,18 +334,20 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait>) -> Result { + fn compress(self, pp: &PublicParams) -> Result { match self { - Self::Recursive(recursive_snark, num_steps) => Ok(Self::Compressed( - Box::new(CompressedSNARK::<_, _, _, _, SS1, SS2>::prove( + Self::Recursive(recursive_snark, num_steps, _phantom) => Ok(Self::Compressed( + Box::new(CompressedSNARK::<_, SS1, SS2>::prove( &pp.pp, pp.pk(), &recursive_snark, )?), num_steps, + PhantomData, )), Self::Compressed(..) => Ok(self), } @@ -362,10 +359,10 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait { + Self::Recursive(p, num_steps, _phantom) => { p.verify(&pp.pp, *num_steps, z0_primary, &z0_secondary)? } - Self::Compressed(p, num_steps) => { + Self::Compressed(p, num_steps, _phantom) => { p.verify(pp.vk(), *num_steps, z0_primary, &z0_secondary)? } }; @@ -399,7 +396,7 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor + 'a> NovaProver<'a, F, C> { /// Generate a proof from a sequence of frames pub fn prove_from_frames( &self, - pp: &PublicParams>, + pp: &PublicParams, frames: &[Frame], store: &'a Store, ) -> Result<(Proof>, Vec, Vec, usize), ProofError> { @@ -419,7 +416,7 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor + 'a> NovaProver<'a, F, C> { impl<'a, F: CurveCycleEquipped, C: Coprocessor + 'a> Prover<'a, F, C1LEM<'a, F, C>> for NovaProver<'a, F, C> { - type PublicParams = PublicParams>; + type PublicParams = PublicParams; type RecursiveSnark = Proof>; #[inline] diff --git a/src/proof/supernova.rs b/src/proof/supernova.rs index 9809be3fea..619143c143 100644 --- a/src/proof/supernova.rs +++ b/src/proof/supernova.rs @@ -3,12 +3,11 @@ use nova::{ self, error::SuperNovaError, snark::{CompressedSNARK, ProverKey, VerifierKey}, - AuxParams, CircuitDigests, NonUniformCircuit, RecursiveSNARK, - StepCircuit as SuperStepCircuit, TrivialSecondaryCircuit, + AuxParams, CircuitDigests, NonUniformCircuit, RecursiveSNARK, TrivialSecondaryCircuit, }, traits::{ snark::{BatchedRelaxedR1CSSNARKTrait, RelaxedR1CSSNARKTrait}, - Engine, + Dual as DualEng, }, }; use once_cell::sync::OnceCell; @@ -29,7 +28,7 @@ use crate::{ field::LurkField, lem::{interpreter::Frame, pointers::Ptr, store::Store}, proof::{ - nova::{CurveCycleEquipped, NovaCircuitShape, E1, E2}, + nova::{CurveCycleEquipped, Dual, NovaCircuitShape, E1}, Prover, RecursiveSNARKTrait, }, }; @@ -37,48 +36,46 @@ use crate::{ use super::{nova::C1LEM, FoldingMode}; /// Type alias for a Trivial Test Circuit with G2 scalar field elements. -pub type C2 = TrivialSecondaryCircuit< as Engine>::Scalar>; +pub type C2 = TrivialSecondaryCircuit>; /// Type alias for SuperNova Aux Parameters with the curve cycle types defined above. -pub type SuperNovaAuxParams = AuxParams, E2>; +pub type SuperNovaAuxParams = AuxParams>; /// Type alias for SuperNova Public Parameters with the curve cycle types defined above. -pub type SuperNovaPublicParams = supernova::PublicParams, E2, C1, C2>; +pub type SuperNovaPublicParams = supernova::PublicParams>; /// A struct that contains public parameters for the SuperNova proving system. -pub struct PublicParams> { +pub struct PublicParams { /// Public params for SuperNova. - pub pp: SuperNovaPublicParams, + pub pp: SuperNovaPublicParams, /// Prover key and Verifier key for SuperNova // TODO: mark as #[serde(skip)] when serializing pub pk_and_vk: OnceCell<( - ProverKey, E2, SC, C2, SS1, SS2>, - VerifierKey, E2, SC, C2, SS1, SS2>, + ProverKey, SS1, SS2>, + VerifierKey, SS1, SS2>, )>, } -impl> PublicParams { +impl PublicParams { /// provides a reference to a ProverKey suitable for producing a CompressedProof - pub fn pk(&self) -> &ProverKey, E2, SC, C2, SS1, SS2> { - let (pk, _vk) = self.pk_and_vk.get_or_init(|| { - CompressedSNARK::, E2, SC, C2, SS1, SS2>::setup(&self.pp).unwrap() - }); + pub fn pk(&self) -> &ProverKey, SS1, SS2> { + let (pk, _vk) = self + .pk_and_vk + .get_or_init(|| CompressedSNARK::, SS1, SS2>::setup(&self.pp).unwrap()); pk } /// provides a reference to a VerifierKey suitable for verifying a CompressedProof - pub fn vk(&self) -> &VerifierKey, E2, SC, C2, SS1, SS2> { - let (_pk, vk) = self.pk_and_vk.get_or_init(|| { - CompressedSNARK::, E2, SC, C2, SS1, SS2>::setup(&self.pp).unwrap() - }); + pub fn vk(&self) -> &VerifierKey, SS1, SS2> { + let (_pk, vk) = self + .pk_and_vk + .get_or_init(|| CompressedSNARK::, SS1, SS2>::setup(&self.pp).unwrap()); vk } } -impl> From> - for PublicParams -{ - fn from(pp: SuperNovaPublicParams) -> PublicParams { +impl From> for PublicParams { + fn from(pp: SuperNovaPublicParams) -> PublicParams { PublicParams { pp, pk_and_vk: OnceCell::new(), @@ -86,7 +83,7 @@ impl> From> Index for PublicParams { +impl Index for PublicParams { type Output = NovaCircuitShape; fn index(&self, index: usize) -> &Self::Output { @@ -94,7 +91,7 @@ impl> Index for PublicPara } } -impl> PublicParams { +impl PublicParams { /// return the digest pub fn digest(&self) -> F { self.pp.digest() @@ -113,21 +110,21 @@ pub type SS1 = nova::spartan::batched::BatchedRelaxedR1CSSNARK, EE1> /// Type alias for the Relaxed R1CS Spartan SNARK using G2 group elements, EE2. // NOTE: this is not a SNARK that uses computational commitments, // that SNARK would be found at nova::spartan::ppsnark::RelaxedR1CSSNARK, -pub type SS2 = nova::spartan::snark::RelaxedR1CSSNARK, EE2>; +pub type SS2 = nova::spartan::snark::RelaxedR1CSSNARK>, EE2>; /// Generates the running claim params for the SuperNova proving system. -pub fn public_params<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( +pub fn public_params>( rc: usize, lang: Arc>, -) -> PublicParams> { +) -> PublicParams { let folding_config = Arc::new(FoldingConfig::new_nivc(lang, rc)); - let non_uniform_circuit = C1LEM::<'a, F, C>::blank(folding_config, 0); + let non_uniform_circuit = C1LEM::<'_, F, C>::blank(folding_config, 0); // grab hints for the compressed SNARK variants we will use this with let commitment_size_hint1 = as BatchedRelaxedR1CSSNARKTrait>>::ck_floor(); - let commitment_size_hint2 = as RelaxedR1CSSNARKTrait>>::ck_floor(); + let commitment_size_hint2 = as RelaxedR1CSSNARKTrait>>>::ck_floor(); - let pp = SuperNovaPublicParams::>::setup( + let pp = SuperNovaPublicParams::::setup( &non_uniform_circuit, &*commitment_size_hint1, &*commitment_size_hint2, @@ -141,11 +138,11 @@ pub fn public_params<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( /// An enum representing the two types of proofs that can be generated and verified. #[derive(Serialize, Deserialize)] #[serde(bound = "")] -pub enum Proof> { +pub enum Proof { /// A proof for the intermediate steps of a recursive computation - Recursive(Box, E2>>), + Recursive(Box>>, PhantomData), /// A proof for the final step of a recursive computation - Compressed(Box, E2, C1, C2, SS1, SS2>>), + Compressed(Box, SS1, SS2>>, PhantomData), } /// A struct for the Nova prover that operates on field elements of type `F`. @@ -174,7 +171,7 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor + 'a> SuperNovaProver<'a, F, C /// Generate a proof from a sequence of frames pub fn prove_from_frames( &self, - pp: &PublicParams>, + pp: &PublicParams, frames: &[Frame], store: &'a Store, ) -> Result<(Proof>, Vec, Vec, usize), ProofError> { @@ -194,18 +191,18 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor + 'a> SuperNovaProver<'a, F, C impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait> for Proof> { - type PublicParams = PublicParams>; + type PublicParams = PublicParams; type ErrorType = SuperNovaError; #[tracing::instrument(skip_all, name = "supernova::prove_recursively")] fn prove_recursively( - pp: &PublicParams>, + pp: &PublicParams, z0: &[F], steps: Vec>, store: &Store, ) -> Result { - let mut recursive_snark_option: Option, E2>> = None; + let mut recursive_snark_option: Option>> = None; let z0_primary = z0; let z0_secondary = Self::z0_secondary(); @@ -293,20 +290,18 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait>) -> Result { + fn compress(self, pp: &PublicParams) -> Result { match &self { - Self::Recursive(recursive_snark) => { - let snark = CompressedSNARK::<_, _, _, _, SS1, SS2>::prove( - &pp.pp, - pp.pk(), - recursive_snark, - )?; - Ok(Self::Compressed(Box::new(snark))) + Self::Recursive(recursive_snark, _phantom) => { + let snark = + CompressedSNARK::<_, SS1, SS2>::prove(&pp.pp, pp.pk(), recursive_snark)?; + Ok(Self::Compressed(Box::new(snark), PhantomData)) } Self::Compressed(..) => Ok(self), } @@ -318,8 +313,10 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait p.verify(&pp.pp, z0_primary, &z0_secondary)?, - Self::Compressed(p) => p.verify(&pp.pp, pp.vk(), z0_primary, &z0_secondary)?, + Self::Recursive(p, _phantom) => p.verify(&pp.pp, z0_primary, &z0_secondary)?, + Self::Compressed(p, _phantom) => { + p.verify(&pp.pp, pp.vk(), z0_primary, &z0_secondary)? + } }; Ok(zi_primary == zi_primary_verified && zi_secondary == &zi_secondary_verified) @@ -329,7 +326,7 @@ impl<'a, F: CurveCycleEquipped, C: Coprocessor> RecursiveSNARKTrait> Prover<'a, F, C1LEM<'a, F, C>> for SuperNovaProver<'a, F, C> { - type PublicParams = PublicParams>; + type PublicParams = PublicParams; type RecursiveSnark = Proof>; #[inline] @@ -423,7 +420,7 @@ pub fn circuit_cache_key<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( let circuit = C1LEM::<'a, F, C>::blank(folding_config, 0); let num_circuits = circuit.num_circuits(); let circuit = circuit.primary_circuit(circuit_index); - F::from(rc as u64) * supernova::circuit_digest::(&circuit, num_circuits) + F::from(rc as u64) * supernova::circuit_digest::(&circuit, num_circuits) } /// Collects all the cache keys of supernova instance. We need all of them to compute diff --git a/src/proof/tests/mod.rs b/src/proof/tests/mod.rs index 649f8d3d10..3bed17ed0b 100644 --- a/src/proof/tests/mod.rs +++ b/src/proof/tests/mod.rs @@ -1,4 +1,4 @@ -mod nova_tests_lem; +mod nova_tests; use bellpepper::util_cs::{metric_cs::MetricCS, witness_cs::WitnessCS, Comparable}; use bellpepper_core::{test_cs::TestConstraintSystem, Circuit, ConstraintSystem, Delta}; use expect_test::Expect; @@ -130,7 +130,8 @@ fn nova_test_full_aux2<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( } assert!(res.unwrap()); - let compressed = proof.compress(&pp).unwrap(); + let compressed: crate::proof::nova::Proof> = + proof.compress(&pp).unwrap(); let res2 = compressed.verify(&pp, &z0, &zi); assert!(res2.unwrap()); diff --git a/src/proof/tests/nova_tests_lem.rs b/src/proof/tests/nova_tests.rs similarity index 100% rename from src/proof/tests/nova_tests_lem.rs rename to src/proof/tests/nova_tests.rs diff --git a/src/public_parameters/disk_cache.rs b/src/public_parameters/disk_cache.rs index 0f23913fa1..87fa3345eb 100644 --- a/src/public_parameters/disk_cache.rs +++ b/src/public_parameters/disk_cache.rs @@ -7,7 +7,7 @@ use camino::{Utf8Path, Utf8PathBuf}; use crate::config::lurk_config; use crate::coprocessor::Coprocessor; -use crate::proof::nova::{CurveCycleEquipped, PublicParams, C1LEM}; +use crate::proof::nova::{CurveCycleEquipped, PublicParams}; use crate::public_parameters::error::Error; use super::instance::Instance; @@ -37,10 +37,7 @@ impl> DiskCache { }) } - pub(crate) fn read<'a>( - &self, - instance: &Instance, - ) -> Result>, Error> { + pub(crate) fn read(&self, instance: &Instance) -> Result, Error> { let file = instance.open(&self.dir)?; let reader = BufReader::new(file); bincode::deserialize_from(reader) @@ -61,7 +58,7 @@ impl> DiskCache { pub(crate) fn write( &self, instance: &Instance, - data: &PublicParams>, + data: &PublicParams, ) -> Result<(), Error> { let file = instance.create(&self.dir)?; let writer = BufWriter::new(&file); diff --git a/src/public_parameters/mod.rs b/src/public_parameters/mod.rs index 1afdbc9c38..01dc7202a2 100644 --- a/src/public_parameters/mod.rs +++ b/src/public_parameters/mod.rs @@ -1,12 +1,12 @@ -use ::nova::{supernova::FlatAuxParams, traits::Engine, FlatPublicParams}; +use ::nova::{supernova::FlatAuxParams, FlatPublicParams}; use abomonation::{decode, Abomonation}; use once_cell::sync::OnceCell; use tap::TapFallible; use tracing::{info, warn}; use crate::coprocessor::Coprocessor; -use crate::proof::nova::{self, NovaCircuitShape, NovaPublicParams, PublicParams, C1LEM}; -use crate::proof::nova::{CurveCycleEquipped, C2, E1, E2}; +use crate::proof::nova::{self, NovaCircuitShape, NovaPublicParams, PublicParams}; +use crate::proof::nova::{CurveCycleEquipped, Dual, E1}; pub mod disk_cache; mod error; @@ -17,12 +17,12 @@ use crate::public_parameters::disk_cache::{public_params_dir, DiskCache}; use crate::public_parameters::error::Error; use crate::public_parameters::instance::Instance; -pub fn public_params<'a, F: CurveCycleEquipped, C: Coprocessor + 'static>( +pub fn public_params>( instance: &Instance, -) -> Result>, Error> +) -> Result, Error> where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + ::Repr: Abomonation, + as ff::PrimeField>::Repr: Abomonation, { let default = |instance: &Instance| nova::public_params(instance.rc, instance.lang()); @@ -35,13 +35,9 @@ where match disk_cache.read_bytes(instance, &mut bytes) { Ok(()) => { info!("loading abomonated {}", instance.key()); - let (pp, rest) = unsafe { - decode::, E2, C1LEM<'a, F, C>, C2>>(&mut bytes) - .unwrap() - }; + let (pp, rest) = unsafe { decode::>>(&mut bytes).unwrap() }; assert!(rest.is_empty()); - let pp = - PublicParams::from(NovaPublicParams::>::from(pp.clone())); // this clone is VERY expensive + let pp = PublicParams::from(NovaPublicParams::::from(pp.clone())); // this clone is VERY expensive Ok(pp) } Err(Error::IO(e)) => { @@ -54,9 +50,7 @@ where .write_abomonated(instance, &fp) .tap_ok(|_| info!("writing public params to disk-cache: {}", instance.key())) .map_err(|e| Error::Cache(format!("Disk write error: {e}")))?; - Ok(PublicParams::from( - NovaPublicParams::>::from(fp), - )) + Ok(PublicParams::from(NovaPublicParams::::from(fp))) } _ => unreachable!(), } @@ -80,8 +74,8 @@ pub fn supernova_circuit_params<'a, F: CurveCycleEquipped, C: Coprocessor + ' instance: &Instance, ) -> Result, Error> where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + ::Repr: Abomonation, + as ff::PrimeField>::Repr: Abomonation, { let disk_cache = DiskCache::::new(public_params_dir()).unwrap(); @@ -101,15 +95,15 @@ pub fn supernova_aux_params<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( instance: &Instance, ) -> Result, Error> where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + ::Repr: Abomonation, + as ff::PrimeField>::Repr: Abomonation, { let disk_cache = DiskCache::::new(public_params_dir()).unwrap(); let mut bytes = vec![]; disk_cache.read_bytes(instance, &mut bytes).and_then(|()| { if let Some((flat_aux_params, remaining)) = - unsafe { decode::, E2>>(&mut bytes) } + unsafe { decode::>>(&mut bytes) } { assert!(remaining.is_empty()); Ok(SuperNovaAuxParams::::from(flat_aux_params.clone())) @@ -122,14 +116,13 @@ where /// Attempts to extract abomonated public parameters. pub fn supernova_public_params<'a, F: CurveCycleEquipped, C: Coprocessor + 'a>( instance_primary: &Instance, -) -> Result>, Error> +) -> Result, Error> where - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, - < as Engine>::Scalar as ff::PrimeField>::Repr: Abomonation, + ::Repr: Abomonation, + as ff::PrimeField>::Repr: Abomonation, { - let default = |instance: &Instance| { - supernova::public_params::<'a, F, C>(instance.rc, instance.lang()) - }; + let default = + |instance: &Instance| supernova::public_params::(instance.rc, instance.lang()); let disk_cache = DiskCache::::new(public_params_dir()).unwrap(); let maybe_circuit_params_vec = instance_primary @@ -145,10 +138,7 @@ where { println!("generating public params"); - let pp = SuperNovaPublicParams::>::from_parts_unchecked( - circuit_params_vec, - aux_params, - ); + let pp = SuperNovaPublicParams::::from_parts_unchecked(circuit_params_vec, aux_params); supernova::PublicParams { pp, @@ -160,7 +150,7 @@ where let (circuit_params_vec, aux_params) = pp.pp.into_parts(); - let flat_aux_params = FlatAuxParams::, E2>::try_from(aux_params).unwrap(); + let flat_aux_params = FlatAuxParams::>::try_from(aux_params).unwrap(); disk_cache.write_abomonated(instance_primary, &flat_aux_params)?; let aux_params = SuperNovaAuxParams::::from(flat_aux_params); @@ -169,10 +159,7 @@ where disk_cache.write_abomonated(&instance, circuit_params)?; } - let pp = SuperNovaPublicParams::>::from_parts_unchecked( - circuit_params_vec, - aux_params, - ); + let pp = SuperNovaPublicParams::::from_parts_unchecked(circuit_params_vec, aux_params); supernova::PublicParams { pp, @@ -197,7 +184,7 @@ mod tests { let tmp_dir = Builder::new().prefix("tmp").tempdir().unwrap(); std::env::set_var("LURK_PUBLIC_PARAMS", tmp_dir.path()); - let lang: Arc>> = Arc::new(Lang::new()); + let lang: Arc> = Arc::new(Lang::new()); let instance = Instance::new(10, lang, true, Kind::NovaPublicParams); // Without disk cache, writes to tmpfile let _public_params = public_params::>(&instance).unwrap();