group: Separate prime and cofactor traits into modules

Instead of having the Group crate hold a Subgroup associated type (and
thus needing to define the subgroup of a prime-order group as itself),
we specify two separate sets of traits for prime-order groups and ones
with a cofactor.

Protocol implementors can either restrict their implementations to only
work with PrimeGroup, or can explicitly choose to support CofactorGroup
and then explicitly handle the subgroup edge cases with e.g.
CofactorGroup::mul_by_cofactor (which would be a no-op for PrimeGroup).

Protocol implementors can also choose to specialise to elliptic curves
if they want to leverage an affine representation and mixed addition in
their protocol for efficiency, or they can ignore those traits and stick
with the simpler group-focused traits.
This commit is contained in:
Jack Grigg 2020-05-30 00:49:44 +12:00
parent a77b2c8623
commit 0c9e783172
7 changed files with 35 additions and 16 deletions

View File

@ -12,7 +12,7 @@
//! [Groth16]: https://eprint.iacr.org/2016/260
use ff::PrimeField;
use group::CofactorCurve;
use group::cofactor::CofactorCurve;
use super::SynthesisError;

View File

@ -3,7 +3,7 @@ use std::ops::{AddAssign, MulAssign};
use std::sync::Arc;
use ff::{Field, PrimeField};
use group::{CurveAffine, CofactorCurve, Group, Wnaf};
use group::{cofactor::CofactorCurveAffine, Curve, Group, Wnaf};
use pairing::Engine;
use super::{Parameters, VerifyingKey};

View File

@ -2,7 +2,7 @@
//!
//! [Groth16]: https://eprint.iacr.org/2016/260
use group::{CurveAffine, GroupEncoding, UncompressedEncoding};
use group::{cofactor::CofactorCurveAffine, GroupEncoding, UncompressedEncoding};
use pairing::{Engine, MultiMillerLoop};
use crate::SynthesisError;

View File

@ -5,7 +5,7 @@ use std::sync::Arc;
use futures::Future;
use ff::{Field, PrimeField};
use group::{CurveAffine, CofactorCurve};
use group::{cofactor::CofactorCurveAffine, Curve};
use pairing::Engine;
use super::{ParameterSource, Proof};

View File

@ -1,5 +1,9 @@
use ff::{Field, PrimeField};
use group::{CurveAffine, CofactorCurve, Group, GroupEncoding, PrimeGroup, UncompressedEncoding};
use group::{
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
prime::PrimeGroup,
Curve, Group, GroupEncoding, UncompressedEncoding,
};
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
use rand_core::RngCore;
@ -367,7 +371,6 @@ impl MillerLoopResult for Fr {
}
impl Group for Fr {
type Subgroup = Fr;
type Scalar = Fr;
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
@ -393,8 +396,20 @@ impl Group for Fr {
impl PrimeGroup for Fr {}
impl CofactorCurve for Fr {
type Affine = Fr;
impl CofactorGroup for Fr {
type Subgroup = Fr;
fn mul_by_cofactor(&self) -> Self::Subgroup {
*self
}
fn into_subgroup(self) -> CtOption<Self::Subgroup> {
CtOption::new(self, Choice::from(1))
}
}
impl Curve for Fr {
type AffineRepr = Fr;
fn to_affine(&self) -> Fr {
*self
@ -409,6 +424,10 @@ impl CofactorCurve for Fr {
}
}
impl CofactorCurve for Fr {
type Affine = Fr;
}
#[derive(Copy, Clone, Default)]
pub struct FakePoint;
@ -424,7 +443,7 @@ impl AsRef<[u8]> for FakePoint {
}
}
impl CurveAffine for Fr {
impl CofactorCurveAffine for Fr {
type Curve = Fr;
type Scalar = Fr;

View File

@ -1,4 +1,4 @@
use group::{CurveAffine, CofactorCurve};
use group::{cofactor::CofactorCurveAffine, Curve};
use pairing::{MillerLoopResult, MultiMillerLoop};
use std::ops::{AddAssign, Neg};

View File

@ -2,7 +2,7 @@ use super::multicore::Worker;
use bit_vec::{self, BitVec};
use ff::{Endianness, Field, PrimeField};
use futures::Future;
use group::{CofactorCurve, CurveAffine};
use group::cofactor::{CofactorCurve, CofactorCurveAffine};
use std::io;
use std::iter;
use std::ops::AddAssign;
@ -11,14 +11,14 @@ use std::sync::Arc;
use super::SynthesisError;
/// An object that builds a source of bases.
pub trait SourceBuilder<G: CurveAffine>: Send + Sync + 'static + Clone {
pub trait SourceBuilder<G: CofactorCurveAffine>: Send + Sync + 'static + Clone {
type Source: Source<G>;
fn new(self) -> Self::Source;
}
/// A source of bases, like an iterator.
pub trait Source<G: CurveAffine> {
pub trait Source<G: CofactorCurveAffine> {
fn next(&mut self) -> Result<&G, SynthesisError>;
/// Skips `amt` elements from the source, avoiding deserialization.
@ -37,7 +37,7 @@ pub trait AddAssignFromSource: CofactorCurve {
}
impl<G> AddAssignFromSource for G where G: CofactorCurve {}
impl<G: CurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
impl<G: CofactorCurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
type Source = (Arc<Vec<G>>, usize);
fn new(self) -> (Arc<Vec<G>>, usize) {
@ -45,7 +45,7 @@ impl<G: CurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
}
}
impl<G: CurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
impl<G: CofactorCurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
fn next(&mut self) -> Result<&G, SynthesisError> {
if self.0.len() <= self.1 {
return Err(io::Error::new(
@ -311,7 +311,7 @@ fn test_with_bls12() {
acc
}
use group::Group;
use group::{Curve, Group};
use pairing::{
bls12_381::{Bls12, Fr},
Engine,