Skip to content

Commit

Permalink
refactor: Refactor trait requirements and update CurveCycleEquipped (#…
Browse files Browse the repository at this point in the history
…847)

**Context**:

Developing [zeromorph](https://github.com/lurk-lab/arecibo/tree/zeromorph) forced me to abstract several Nova APIs over the used `EvaluationEngineTrait` (which was the point of the whole exercise).
And it forced me to realize that Nova APIs that genericise over the group implementations, in order to represent the concept of a given curve cycle, become a lot simpler when they jointly abstract over the associated `EvaluationEngine`.

This insight led to microsoft/Nova#234

**This PR**:

We prepare the code base from where it is now (hard-coding that the Evaluation Engine used in nova is the IPA, and requiring the corresponding idiosyncratic trait bound `CommitmentKeyExtTrait`) to
something that's Zeromorph-ready (recognizing that any curve cycle may have its unspecified choice of `EvaluationEngineTrait` implementations). We reap the associated simplicity benefits.

**In Detail**:

- Removed Sync and Send trait requirements for multiple associated types across various modules, simplifying the codebase.
- Significant updates made to the trait `CurveCycleEquipped` in `nova.rs`. Removed four previous type and introduced two new ones, `EE1` and `EE2`, shifting the focus towards an improved Evaluation Engine.
- This change in trait `CurveCycleEquipped` is also reflected in the pallas::Scalar and bn256::Scalar trait implementations.
- The necessity for detailed explanations about the removed type aliases in `CurveCycleEquipped` was eliminated. Added brief explanations for the new type aliases.
- Removed `Sync + Send` trait bounds from `F::CK1` and `F::CK2` in the `public_params`, `supernova_circuit_params`, and `supernova_aux_params` functions, resulting in simpler functions.
  • Loading branch information
huitseeker authored Nov 7, 2023
1 parent 0476f92 commit b0c1dd4
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 54 deletions.
4 changes: 0 additions & 4 deletions src/cli/lurk_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ impl<'a, F: CurveCycleEquipped + Serialize, M: MultiFrameTrait<'a, F, Coproc<F>>
where
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<F as CurveCycleEquipped>::CK1: Sync + Send,
<F as CurveCycleEquipped>::CK2: Sync + Send,
{
#[inline]
pub(crate) fn persist(self, proof_key: &str) -> Result<()> {
Expand All @@ -119,8 +117,6 @@ impl<
where
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<F as CurveCycleEquipped>::CK1: Sync + Send,
<F as CurveCycleEquipped>::CK2: Sync + Send,
{
pub(crate) fn verify_proof(proof_key: &str) -> Result<()> {
let lurk_proof: LurkProof<'_, F, Coproc<F>, M> = load(&proof_path(proof_key))?;
Expand Down
3 changes: 0 additions & 3 deletions src/cli/repl/meta_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,8 @@ impl MetaCmd<F> {

impl<F: CurveCycleEquipped + DeserializeOwned> MetaCmd<F>
where
// TODO(huitseeker): this is a bit pedantic, revisit later.
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<F as CurveCycleEquipped>::CK1: Sync + Send,
<F as CurveCycleEquipped>::CK2: Sync + Send,
{
const VERIFY: MetaCmd<F> = MetaCmd {
name:
Expand Down
58 changes: 21 additions & 37 deletions src/proof/nova.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ use ff::Field;
use nova::{
errors::NovaError,
provider::bn256_grumpkin::{bn256, grumpkin},
provider::pedersen::CommitmentKeyExtTrait,
traits::{
circuit::{StepCircuit, TrivialCircuit},
commitment::CommitmentEngineTrait,
evaluation::EvaluationEngineTrait,
snark::RelaxedR1CSSNARKTrait,
Group,
},
Expand Down Expand Up @@ -45,53 +44,38 @@ use crate::{
/// (currently Pallas/Vesta and BN254/Grumpkin). It being pegged on the `LurkField` trait encodes that we do
/// not expect more than one such cycle to be supported at a time for a given field.
pub trait CurveCycleEquipped: LurkField {
/// ## Why the next 4 types?
///
/// The next 4 types are purely technical, and aim at laying out type bounds in a way that rust can find them.
/// They should eventually be replaceable by a bound on projections, once bounds on associated types progress.
/// They are technically equivalent to bounds of
/// <Self::G1::CE as CommitmentEngineTrait<Self::G1>>::CommitmentKey: CommitmentKeyExtTrait<Self::G1, CE = <Self::G1 as Group>::CE>,
/// <Self::G2::CE as CommitmentEngineTrait<Self::G2>>::CommitmentKey: CommitmentKeyExtTrait<Self::G2, CE = <G2 as Group>::CE>,
/// but where clauses can't be *found* by the compiler at the point where Self::G1, Self::G2 are used
/// ## OK, but why do we need bounds at all in the first place?
/// ## Why the next 2 types?
/// In theory it would be sufficient to abstract over the two group types of the curve cycle, but in practice Nova is a
/// bit idiosyncratic in the [`nova::traits::evaluation::EvaluationEngineTrait<G>`], (PCS) it uses on these (its multilinear IPA : [`nova::provider::ipa_pc::EvaluationEngine<G>`])
/// *and* that implementation requires an additional trait bound `CommitmentKeyExtTrait` for this type.
///
/// As to *why* those see https://github.com/microsoft/Nova/pull/200
/// and the bound `CommitmentKey<G>: CommitmentKeyExtTrait<G, CE = G::CE>` on [`nova::provider::ipa_pc::EvaluationEngine<G>`]
/// Essentially, Nova relies on a commitment scheme that is additively homomorphic, but encodes the practicalities of this
/// (properties are unwieldy to encode) in the form of this CommitmentKeyExtTrait.
/// The type of the commitment key used for points of the first curve in the cycle.
type CK1: CommitmentKeyExtTrait<Self::G1>;
/// The type of the commitment key used for points of the second curve in the cycle.
type CK2: CommitmentKeyExtTrait<Self::G2>;
/// The commitment engine type for the first curve in the cycle.
type CE1: CommitmentEngineTrait<Self::G1, CommitmentKey = Self::CK1>;
/// The commitment engine type for the second curve in the cycle.
type CE2: CommitmentEngineTrait<Self::G2, CommitmentKey = Self::CK2>;
/// The following abstracts over curve cycle groups for which there exists an implementation of [`nova::traits::evaluation::EvaluationEngineTrait<G>`],
/// encapsulating these idiosyncracies within Nova.
/// a concrete implementation of an [`nova::traits::evaluation::EvaluationEngineTrait<G>`] for G1,
type EE1: EvaluationEngineTrait<Self::G1>;
/// a concrete implementation of an [`nova::traits::evaluation::EvaluationEngineTrait<G>`] for G2,
type EE2: EvaluationEngineTrait<Self::G2>;

/// The group type for the first curve in the cycle.
type G1: Group<Base = <Self::G2 as Group>::Scalar, Scalar = Self, CE = Self::CE1>;
type G1: Group<Base = <Self::G2 as Group>::Scalar, Scalar = Self>;
/// The group type for the second curve in the cycle.
type G2: Group<Base = <Self::G1 as Group>::Scalar, CE = Self::CE2>;
type G2: Group<Base = <Self::G1 as Group>::Scalar>;
}

impl CurveCycleEquipped for pallas::Scalar {
type CK1 = nova::provider::pedersen::CommitmentKey<pallas::Point>;
type CK2 = nova::provider::pedersen::CommitmentKey<vesta::Point>;
type CE1 = nova::provider::pedersen::CommitmentEngine<pallas::Point>;
type CE2 = nova::provider::pedersen::CommitmentEngine<vesta::Point>;
type EE1 = nova::provider::ipa_pc::EvaluationEngine<Self::G1>;
type EE2 = nova::provider::ipa_pc::EvaluationEngine<Self::G2>;

type G1 = pallas::Point;
type G2 = vesta::Point;
}
// The impl CurveCycleEquipped for vesta::Scalar is academically possible, but voluntarily omitted to avoid confusion.

impl CurveCycleEquipped for bn256::Scalar {
type CK1 = nova::provider::pedersen::CommitmentKey<bn256::Point>;
type CK2 = nova::provider::pedersen::CommitmentKey<grumpkin::Point>;
type CE1 = nova::provider::pedersen::CommitmentEngine<bn256::Point>;
type CE2 = nova::provider::pedersen::CommitmentEngine<grumpkin::Point>;
type EE1 = nova::provider::ipa_pc::EvaluationEngine<Self::G1>;
type EE2 = nova::provider::ipa_pc::EvaluationEngine<Self::G2>;

type G1 = bn256::Point;
type G2 = grumpkin::Point;
Expand All @@ -104,9 +88,9 @@ pub type G1<F> = <F as CurveCycleEquipped>::G1;
pub type G2<F> = <F as CurveCycleEquipped>::G2;

/// Type alias for the Evaluation Engine using G1 group elements.
pub type EE1<F> = nova::provider::ipa_pc::EvaluationEngine<G1<F>>;
pub type EE1<F> = <F as CurveCycleEquipped>::EE1;
/// Type alias for the Evaluation Engine using G2 group elements.
pub type EE2<F> = nova::provider::ipa_pc::EvaluationEngine<G2<F>>;
pub type EE2<F> = <F as CurveCycleEquipped>::EE2;

/// Type alias for the Relaxed R1CS Spartan SNARK using G1 group elements, EE1.
// NOTE: this is not a SNARK that uses computational commitments,
Expand Down
2 changes: 0 additions & 2 deletions src/public_parameters/mem_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ impl PublicParamMemCache {
default: Fn,
) -> Result<Arc<PublicParams<F, M>>, Error>
where
F::CK1: Sync + Send,
F::CK2: Sync + Send,
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
{
Expand Down
8 changes: 0 additions & 8 deletions src/public_parameters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ pub fn public_params<
instance: &Instance<'static, F, C, M>,
) -> Result<Arc<PublicParams<F, M>>, Error>
where
F::CK1: Sync + Send,
F::CK2: Sync + Send,
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
{
Expand Down Expand Up @@ -90,8 +88,6 @@ pub fn supernova_circuit_params<
instance: &Instance<'a, F, C, M>,
) -> Result<NovaCircuitShape<F>, Error>
where
F::CK1: Sync + Send,
F::CK2: Sync + Send,
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
{
Expand All @@ -118,8 +114,6 @@ pub fn supernova_aux_params<
instance: &Instance<'a, F, C, M>,
) -> Result<SuperNovaAuxParams<F>, Error>
where
F::CK1: Sync + Send,
F::CK2: Sync + Send,
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
{
Expand Down Expand Up @@ -151,8 +145,6 @@ pub fn supernova_public_params<
instance_primary: &Instance<'a, F, C, M>,
) -> Result<supernova::PublicParams<F, M>, Error>
where
F::CK1: Sync + Send,
F::CK2: Sync + Send,
<<G1<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
<<G2<F> as Group>::Scalar as ff::PrimeField>::Repr: Abomonation,
{
Expand Down

1 comment on commit b0c1dd4

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarks

Table of Contents

Overview

This benchmark report shows the Fibonacci GPU benchmark.
NVIDIA GeForce RTX 4070
AMD Ryzen 9 3950X 16-Core Processor
125.711 GB RAM

Benchmark Results

LEM Fibonacci Prove - rc = 100

fib-ref=0476f921d985b6cd2a150b56a163ee3be9e2abdc fib-ref=b0c1dd456b3d149fc8da897f6005ebeb3b35e7ee
num-100 3.97 s (✅ 1.00x) 4.05 s (✅ 1.02x slower)
num-200 9.10 s (✅ 1.00x) 8.67 s (✅ 1.05x faster)

LEM Fibonacci Prove - rc = 600

fib-ref=0476f921d985b6cd2a150b56a163ee3be9e2abdc fib-ref=b0c1dd456b3d149fc8da897f6005ebeb3b35e7ee
num-100 3.05 s (✅ 1.00x) 3.06 s (✅ 1.00x slower)
num-200 7.04 s (✅ 1.00x) 7.01 s (✅ 1.00x faster)

Made with criterion-table

Please sign in to comment.