Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

New core implementation #15

Open
ebfull opened this issue Dec 9, 2016 · 1 comment
Open

New core implementation #15

ebfull opened this issue Dec 9, 2016 · 1 comment

Comments

@ebfull
Copy link
Contributor

ebfull commented Dec 9, 2016

I'm designing a new "core" for the cryptography in this library, mostly in the interest of performance and flexibility.

Features include:

  • The library will support multiple BN curve implementations all behind this abstract API. In particular, I plan to integrate a stronger curve construction which should be more secure and more useful for zk-SNARKs.
  • The user can perform miller loops (with any number of point tuples) manually if they want to avoid unnecessary final exponentiations or redundant ate loops. The Ethereum folks will need to expose all of this functionality in their precompiles if they want to give users maximum performance and flexibility, especially if you need to use newer zk-SNARK schemes or do batch/probablistic verification of proofs.
  • The user can perform G2 precomputation for the miller loop manually.
  • Support for mixed addition.
  • Support for curve point compression (the same way that Zcash compresses proofs).

API preview:

pub trait Field<E: Engine>: Sized +
                            Eq +
                            PartialEq +
                            Copy +
                            Clone +
                            Send +
                            Sync +
                            Debug +
                            'static
{
    fn zero() -> Self;
    fn one(&E) -> Self;
    fn random<R: rand::Rng>(&E, &mut R) -> Self;

    fn is_zero(&self) -> bool;
    
    fn square(&mut self, &E);
    fn double(&mut self, &E);
    fn negate(&mut self, &E);
    fn add_assign(&mut self, &E, other: &Self);
    fn sub_assign(&mut self, &E, other: &Self);
    fn mul_assign(&mut self, &E, other: &Self);
    fn inverse(&self, &E) -> Option<Self>;
    fn sqrt(&self, &E) -> Option<Self>;
    fn powi<I: IntoIterator<Item=u64>>(&self, engine: &E, exp: I) -> Self;
    fn powb<I: IntoIterator<Item=bool>>(&self, engine: &E, exp: I) -> Self;
}

pub trait PrimeField<E: Engine>: Field<E>
{
    type Repr: AsRef<[u64]>;

    fn from_str(&E, s: &str) -> Result<Self, ()>;
    fn from_repr(&E, Self::Repr) -> Result<Self, ()>;
    fn into_repr(&self, &E) -> Self::Repr;
}

/// A representation of a group element that can be serialized and deserialized,
/// but is not guaranteed to be a point on the curve.
pub trait GroupRepresentation<E: Engine, F: Field<E>, G: Group<E, F>>: Copy +
                                                                       Clone +
                                                                       Sized +
                                                                       Send +
                                                                       Sync +
                                                                       Debug +
                                                                       'static
{
    /// Attempt to parse the representation as an element on
    /// the curve in the affine.
    fn to_affine(&self, &E) -> Option<G::Affine>;

    /// This is like `to_affine` except the caller is
    /// responsible for ensuring the point is on the curve.
    /// If it isn't, this function is allowed to panic,
    /// but not guaranteed to.
    fn to_affine_unchecked(&self, &E) -> G::Affine;
}

pub trait GroupAffine<E: Engine, F: Field<E>, G: Group<E, F>>: Copy +
                                                               Clone +
                                                               Sized +
                                                               Send +
                                                               Sync +
                                                               Debug +
                                                               PartialEq +
                                                               Eq +
                                                               'static
{
    fn to_jacobian(&self, &E) -> G;
    fn to_compressed(&self, &E) -> G::Compressed;
    fn to_uncompressed(&self, &E) -> G::Uncompressed;
}

pub trait Group<E: Engine, F: Field<E>>: Sized +
                                         Eq +
                                         PartialEq +
                                         Copy +
                                         Clone +
                                         Send +
                                         Sync +
                                         Debug +
                                         'static
{
    type Affine: GroupAffine<E, F, Self>;
    type Compressed: GroupRepresentation<E, F, Self>;
    type Uncompressed: GroupRepresentation<E, F, Self>;
    type Prepared: Clone + 'static;

    fn zero(&E) -> Self;
    fn one(&E) -> Self;
    fn random<R: rand::Rng>(&E, &mut R) -> Self;

    fn is_zero(&E) -> Self;

    fn to_affine(&self, &E) -> Self::Affine;
    fn prepare(&self, &E) -> Self::Prepared;

    fn double(&mut self, &E);
    fn negate(&mut self, engine: &E);
    fn add_assign(&mut self, &E, other: &Self);
    fn add_assign_mixed(&mut self, &E, other: &Self::Affine);
    fn mul_assign(&mut self, &E, other: &E::Fr);
}

pub trait Engine: Sized {
    type Fq: PrimeField<Self>;
    type Fr: PrimeField<Self>;
    type Fqe: Field<Self>;
    type Fqk: Field<Self>;
    type G1: Group<Self, Self::Fq>;
    type G2: Group<Self, Self::Fqe>;

    fn new() -> Self;

    fn miller_loop<'a, I>(&self, I) -> Self::Fqk
        where I: IntoIterator<Item=&'a (
                                    &'a <Self::G1 as Group<Self, Self::Fq>>::Prepared,
                                    &'a <Self::G2 as Group<Self, Self::Fqe>>::Prepared
                               )>;

    fn final_exponentiation(&self, &Self::Fqk) -> Self::Fqk;

    fn pairing(&self, p: &Self::G1, q: &Self::G2) -> Self::Fqk
    {
        self.final_exponentiation(&self.miller_loop(
            [(&p.prepare(self), &q.prepare(self))].into_iter()
        ))
    }
}
@zookozcash
Copy link

Very cool. :-) Can't wait to see it.

mersinvald pushed a commit to etclabscore/bn that referenced this issue Jan 9, 2019
Problems: tests need expected output schema and CI fails due to incorrect SHA256
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants