pairing: Move PairingCurveAffine::Prepared to MultiMillerLoop trait
Prepared elements are only used by MultiMillerLoop, and we don't need the ability to "prepare" G1 elements there.
This commit is contained in:
parent
b9d6df9133
commit
03f086221b
|
@ -3,7 +3,7 @@
|
||||||
//! [Groth16]: https://eprint.iacr.org/2016/260
|
//! [Groth16]: https://eprint.iacr.org/2016/260
|
||||||
|
|
||||||
use group::CurveAffine;
|
use group::CurveAffine;
|
||||||
use pairing::{Engine, PairingCurveAffine};
|
use pairing::{Engine, MultiMillerLoop};
|
||||||
|
|
||||||
use crate::SynthesisError;
|
use crate::SynthesisError;
|
||||||
|
|
||||||
|
@ -398,13 +398,13 @@ impl<E: Engine> Parameters<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PreparedVerifyingKey<E: Engine> {
|
pub struct PreparedVerifyingKey<E: MultiMillerLoop> {
|
||||||
/// Pairing result of alpha*beta
|
/// Pairing result of alpha*beta
|
||||||
alpha_g1_beta_g2: E::Gt,
|
alpha_g1_beta_g2: E::Gt,
|
||||||
/// -gamma in G2
|
/// -gamma in G2
|
||||||
neg_gamma_g2: <E::G2Affine as PairingCurveAffine>::Prepared,
|
neg_gamma_g2: E::G2Prepared,
|
||||||
/// -delta in G2
|
/// -delta in G2
|
||||||
neg_delta_g2: <E::G2Affine as PairingCurveAffine>::Prepared,
|
neg_delta_g2: E::G2Prepared,
|
||||||
/// Copy of IC from `VerifiyingKey`.
|
/// Copy of IC from `VerifiyingKey`.
|
||||||
ic: Vec<E::G1Affine>,
|
ic: Vec<E::G1Affine>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,20 +338,16 @@ impl Engine for DummyEngine {
|
||||||
type Gt = Fr;
|
type Gt = Fr;
|
||||||
|
|
||||||
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
|
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
|
||||||
Self::multi_miller_loop(&[(p, &(q.prepare()))]).final_exponentiation()
|
Self::multi_miller_loop(&[(p, &(*q).into())]).final_exponentiation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MultiMillerLoop for DummyEngine {
|
impl MultiMillerLoop for DummyEngine {
|
||||||
|
type G2Prepared = Fr;
|
||||||
// TODO: This should be F_645131 or something. Doesn't matter for now.
|
// TODO: This should be F_645131 or something. Doesn't matter for now.
|
||||||
type Result = Fr;
|
type Result = Fr;
|
||||||
|
|
||||||
fn multi_miller_loop(
|
fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
|
||||||
terms: &[(
|
|
||||||
&Self::G1Affine,
|
|
||||||
&<Self::G2Affine as PairingCurveAffine>::Prepared,
|
|
||||||
)],
|
|
||||||
) -> Self::Result {
|
|
||||||
let mut acc = <Fr as Field>::zero();
|
let mut acc = <Fr as Field>::zero();
|
||||||
|
|
||||||
for &(a, b) in terms {
|
for &(a, b) in terms {
|
||||||
|
@ -487,14 +483,9 @@ impl CurveAffine for Fr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PairingCurveAffine for Fr {
|
impl PairingCurveAffine for Fr {
|
||||||
type Prepared = Fr;
|
|
||||||
type Pair = Fr;
|
type Pair = Fr;
|
||||||
type PairingResult = Fr;
|
type PairingResult = Fr;
|
||||||
|
|
||||||
fn prepare(&self) -> Self::Prepared {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
|
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
|
||||||
self.mul(*other)
|
self.mul(*other)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
use group::{CurveAffine, CurveProjective};
|
use group::{CurveAffine, CurveProjective};
|
||||||
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
use pairing::{MillerLoopResult, MultiMillerLoop};
|
||||||
use std::ops::{AddAssign, Neg};
|
use std::ops::{AddAssign, Neg};
|
||||||
|
|
||||||
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
use super::{PreparedVerifyingKey, Proof, VerifyingKey};
|
||||||
|
|
||||||
use crate::SynthesisError;
|
use crate::SynthesisError;
|
||||||
|
|
||||||
pub fn prepare_verifying_key<E: Engine>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
|
pub fn prepare_verifying_key<E: MultiMillerLoop>(vk: &VerifyingKey<E>) -> PreparedVerifyingKey<E> {
|
||||||
let gamma = vk.gamma_g2.neg();
|
let gamma = vk.gamma_g2.neg();
|
||||||
let delta = vk.delta_g2.neg();
|
let delta = vk.delta_g2.neg();
|
||||||
|
|
||||||
PreparedVerifyingKey {
|
PreparedVerifyingKey {
|
||||||
alpha_g1_beta_g2: E::pairing(&vk.alpha_g1, &vk.beta_g2),
|
alpha_g1_beta_g2: E::pairing(&vk.alpha_g1, &vk.beta_g2),
|
||||||
neg_gamma_g2: gamma.prepare(),
|
neg_gamma_g2: gamma.into(),
|
||||||
neg_delta_g2: delta.prepare(),
|
neg_delta_g2: delta.into(),
|
||||||
ic: vk.ic.clone(),
|
ic: vk.ic.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ pub fn verify_proof<'a, E: MultiMillerLoop>(
|
||||||
// which allows us to do a single final exponentiation.
|
// which allows us to do a single final exponentiation.
|
||||||
|
|
||||||
Ok(E::multi_miller_loop(&[
|
Ok(E::multi_miller_loop(&[
|
||||||
(&proof.a, &proof.b.prepare()),
|
(&proof.a, &proof.b.into()),
|
||||||
(&acc.to_affine(), &pvk.neg_gamma_g2),
|
(&acc.to_affine(), &pvk.neg_gamma_g2),
|
||||||
(&proof.c, &pvk.neg_delta_g2),
|
(&proof.c, &pvk.neg_delta_g2),
|
||||||
])
|
])
|
||||||
|
|
|
@ -12,26 +12,6 @@ use group::Group;
|
||||||
use pairing::bls12_381::*;
|
use pairing::bls12_381::*;
|
||||||
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
||||||
|
|
||||||
fn bench_pairing_g1_preparation(c: &mut Criterion) {
|
|
||||||
const SAMPLES: usize = 1000;
|
|
||||||
|
|
||||||
let mut rng = XorShiftRng::from_seed([
|
|
||||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
|
||||||
0xe5,
|
|
||||||
]);
|
|
||||||
|
|
||||||
let v: Vec<G1> = (0..SAMPLES).map(|_| G1::random(&mut rng)).collect();
|
|
||||||
|
|
||||||
let mut count = 0;
|
|
||||||
c.bench_function("G1 preparation", |b| {
|
|
||||||
b.iter(|| {
|
|
||||||
let tmp = G1Affine::from(v[count]).prepare();
|
|
||||||
count = (count + 1) % SAMPLES;
|
|
||||||
tmp
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bench_pairing_g2_preparation(c: &mut Criterion) {
|
fn bench_pairing_g2_preparation(c: &mut Criterion) {
|
||||||
const SAMPLES: usize = 1000;
|
const SAMPLES: usize = 1000;
|
||||||
|
|
||||||
|
@ -45,7 +25,7 @@ fn bench_pairing_g2_preparation(c: &mut Criterion) {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
c.bench_function("G2 preparation", |b| {
|
c.bench_function("G2 preparation", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let tmp = G2Affine::from(v[count]).prepare();
|
let tmp = G2Prepared::from(G2Affine::from(v[count]));
|
||||||
count = (count + 1) % SAMPLES;
|
count = (count + 1) % SAMPLES;
|
||||||
tmp
|
tmp
|
||||||
})
|
})
|
||||||
|
@ -64,7 +44,7 @@ fn bench_pairing_miller_loop(c: &mut Criterion) {
|
||||||
.map(|_| {
|
.map(|_| {
|
||||||
(
|
(
|
||||||
G1Affine::from(G1::random(&mut rng)),
|
G1Affine::from(G1::random(&mut rng)),
|
||||||
G2Affine::from(G2::random(&mut rng)).prepare(),
|
G2Affine::from(G2::random(&mut rng)).into(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -91,7 +71,7 @@ fn bench_pairing_final_exponentiation(c: &mut Criterion) {
|
||||||
.map(|_| {
|
.map(|_| {
|
||||||
(
|
(
|
||||||
G1Affine::from(G1::random(&mut rng)),
|
G1Affine::from(G1::random(&mut rng)),
|
||||||
G2Affine::from(G2::random(&mut rng)).prepare(),
|
G2Affine::from(G2::random(&mut rng)).into(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(|(ref p, ref q)| Bls12::multi_miller_loop(&[(p, q)]))
|
.map(|(ref p, ref q)| Bls12::multi_miller_loop(&[(p, q)]))
|
||||||
|
@ -131,7 +111,6 @@ fn bench_pairing_full(c: &mut Criterion) {
|
||||||
|
|
||||||
criterion_group!(
|
criterion_group!(
|
||||||
benches,
|
benches,
|
||||||
bench_pairing_g1_preparation,
|
|
||||||
bench_pairing_g2_preparation,
|
bench_pairing_g2_preparation,
|
||||||
bench_pairing_miller_loop,
|
bench_pairing_miller_loop,
|
||||||
bench_pairing_final_exponentiation,
|
bench_pairing_final_exponentiation,
|
||||||
|
|
|
@ -3,7 +3,6 @@ macro_rules! curve_impl {
|
||||||
$name:expr,
|
$name:expr,
|
||||||
$projective:ident,
|
$projective:ident,
|
||||||
$affine:ident,
|
$affine:ident,
|
||||||
$prepared:ident,
|
|
||||||
$basefield:ident,
|
$basefield:ident,
|
||||||
$scalarfield:ident,
|
$scalarfield:ident,
|
||||||
$uncompressed:ident,
|
$uncompressed:ident,
|
||||||
|
@ -281,14 +280,9 @@ macro_rules! curve_impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PairingCurveAffine for $affine {
|
impl PairingCurveAffine for $affine {
|
||||||
type Prepared = $prepared;
|
|
||||||
type Pair = $pairing;
|
type Pair = $pairing;
|
||||||
type PairingResult = Fq12;
|
type PairingResult = Fq12;
|
||||||
|
|
||||||
fn prepare(&self) -> Self::Prepared {
|
|
||||||
$prepared::from_affine(*self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
|
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult {
|
||||||
self.perform_pairing(other)
|
self.perform_pairing(other)
|
||||||
}
|
}
|
||||||
|
@ -917,7 +911,6 @@ pub mod g1 {
|
||||||
"G1",
|
"G1",
|
||||||
G1,
|
G1,
|
||||||
G1Affine,
|
G1Affine,
|
||||||
G1Prepared,
|
|
||||||
Fq,
|
Fq,
|
||||||
Fr,
|
Fr,
|
||||||
G1Uncompressed,
|
G1Uncompressed,
|
||||||
|
@ -1173,19 +1166,6 @@ pub mod g1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct G1Prepared(pub(crate) G1Affine);
|
|
||||||
|
|
||||||
impl G1Prepared {
|
|
||||||
pub fn is_identity(&self) -> bool {
|
|
||||||
self.0.is_identity().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_affine(p: G1Affine) -> Self {
|
|
||||||
G1Prepared(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn g1_generator() {
|
fn g1_generator() {
|
||||||
let mut x = Fq::zero();
|
let mut x = Fq::zero();
|
||||||
|
@ -1507,7 +1487,6 @@ pub mod g2 {
|
||||||
"G2",
|
"G2",
|
||||||
G2,
|
G2,
|
||||||
G2Affine,
|
G2Affine,
|
||||||
G2Prepared,
|
|
||||||
Fq2,
|
Fq2,
|
||||||
Fr,
|
Fr,
|
||||||
G2Uncompressed,
|
G2Uncompressed,
|
||||||
|
@ -1818,6 +1797,12 @@ pub mod g2 {
|
||||||
pub(crate) infinity: bool,
|
pub(crate) infinity: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<G2Affine> for G2Prepared {
|
||||||
|
fn from(val: G2Affine) -> Self {
|
||||||
|
Self::from_affine(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn g2_generator() {
|
fn g2_generator() {
|
||||||
let mut x = Fq2::zero();
|
let mut x = Fq2::zero();
|
||||||
|
|
|
@ -12,8 +12,8 @@ mod fr;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
pub use self::ec::{
|
pub use self::ec::{
|
||||||
G1Affine, G1Compressed, G1Prepared, G1Uncompressed, G2Affine, G2Compressed, G2Prepared,
|
G1Affine, G1Compressed, G1Uncompressed, G2Affine, G2Compressed, G2Prepared, G2Uncompressed, G1,
|
||||||
G2Uncompressed, G1, G2,
|
G2,
|
||||||
};
|
};
|
||||||
pub use self::fq::{Fq, FqRepr};
|
pub use self::fq::{Fq, FqRepr};
|
||||||
pub use self::fq12::Fq12;
|
pub use self::fq12::Fq12;
|
||||||
|
@ -21,7 +21,7 @@ pub use self::fq2::Fq2;
|
||||||
pub use self::fq6::Fq6;
|
pub use self::fq6::Fq6;
|
||||||
pub use self::fr::{Fr, FrRepr};
|
pub use self::fr::{Fr, FrRepr};
|
||||||
|
|
||||||
use super::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
|
use super::{Engine, MillerLoopResult, MultiMillerLoop};
|
||||||
|
|
||||||
use ff::{BitIterator, Field, ScalarEngine};
|
use ff::{BitIterator, Field, ScalarEngine};
|
||||||
use group::CurveAffine;
|
use group::CurveAffine;
|
||||||
|
@ -46,19 +46,15 @@ impl Engine for Bls12 {
|
||||||
type Gt = Fq12;
|
type Gt = Fq12;
|
||||||
|
|
||||||
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
|
fn pairing(p: &Self::G1Affine, q: &Self::G2Affine) -> Self::Gt {
|
||||||
Self::multi_miller_loop(&[(p, &(q.prepare()))]).final_exponentiation()
|
Self::multi_miller_loop(&[(p, &(*q).into())]).final_exponentiation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MultiMillerLoop for Bls12 {
|
impl MultiMillerLoop for Bls12 {
|
||||||
|
type G2Prepared = G2Prepared;
|
||||||
type Result = Fq12;
|
type Result = Fq12;
|
||||||
|
|
||||||
fn multi_miller_loop(
|
fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result {
|
||||||
terms: &[(
|
|
||||||
&Self::G1Affine,
|
|
||||||
&<Self::G2Affine as PairingCurveAffine>::Prepared,
|
|
||||||
)],
|
|
||||||
) -> Self::Result {
|
|
||||||
let mut pairs = vec![];
|
let mut pairs = vec![];
|
||||||
for &(p, q) in terms {
|
for &(p, q) in terms {
|
||||||
if !bool::from(p.is_identity()) && !q.is_identity() {
|
if !bool::from(p.is_identity()) && !q.is_identity() {
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub mod tests;
|
||||||
pub mod bls12_381;
|
pub mod bls12_381;
|
||||||
|
|
||||||
use core::ops::Mul;
|
use core::ops::Mul;
|
||||||
use ff::{Field, PrimeField, ScalarEngine};
|
use ff::{Field, ScalarEngine};
|
||||||
use group::{CurveAffine, CurveProjective, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned};
|
use group::{CurveAffine, CurveProjective, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned};
|
||||||
|
|
||||||
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
||||||
|
@ -75,30 +75,24 @@ pub trait Engine: ScalarEngine {
|
||||||
/// Affine representation of an elliptic curve point that can be used
|
/// Affine representation of an elliptic curve point that can be used
|
||||||
/// to perform pairings.
|
/// to perform pairings.
|
||||||
pub trait PairingCurveAffine: CurveAffine {
|
pub trait PairingCurveAffine: CurveAffine {
|
||||||
type Prepared: Clone + Send + Sync + 'static;
|
|
||||||
type Pair: PairingCurveAffine<Pair = Self>;
|
type Pair: PairingCurveAffine<Pair = Self>;
|
||||||
type PairingResult: Field;
|
type PairingResult: Field;
|
||||||
|
|
||||||
/// Prepares this element for pairing purposes.
|
|
||||||
fn prepare(&self) -> Self::Prepared;
|
|
||||||
|
|
||||||
/// Perform a pairing
|
/// Perform a pairing
|
||||||
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
|
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An engine that can compute sums of pairings in an efficient way.
|
/// An engine that can compute sums of pairings in an efficient way.
|
||||||
pub trait MultiMillerLoop: Engine {
|
pub trait MultiMillerLoop: Engine {
|
||||||
|
/// The prepared form of `Self::G2Affine`.
|
||||||
|
type G2Prepared: Clone + Send + Sync + From<Self::G2Affine>;
|
||||||
|
|
||||||
/// The type returned by `Engine::miller_loop`.
|
/// The type returned by `Engine::miller_loop`.
|
||||||
type Result: MillerLoopResult<Gt = Self::Gt>;
|
type Result: MillerLoopResult<Gt = Self::Gt>;
|
||||||
|
|
||||||
/// Computes $$\sum_{i=1}^n \textbf{ML}(a_i, b_i)$$ given a series of terms
|
/// Computes $$\sum_{i=1}^n \textbf{ML}(a_i, b_i)$$ given a series of terms
|
||||||
/// $$(a_1, b_1), (a_2, b_2), ..., (a_n, b_n).$$
|
/// $$(a_1, b_1), (a_2, b_2), ..., (a_n, b_n).$$
|
||||||
fn multi_miller_loop(
|
fn multi_miller_loop(terms: &[(&Self::G1Affine, &Self::G2Prepared)]) -> Self::Result;
|
||||||
terms: &[(
|
|
||||||
&Self::G1Affine,
|
|
||||||
&<Self::G2Affine as PairingCurveAffine>::Prepared,
|
|
||||||
)],
|
|
||||||
) -> Self::Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents results of a Miller loop, one of the most expensive portions of the pairing
|
/// Represents results of a Miller loop, one of the most expensive portions of the pairing
|
||||||
|
|
|
@ -22,12 +22,12 @@ pub fn engine_tests<E: MultiMillerLoop>() {
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
let z1 = E::G1Affine::identity();
|
let z1 = E::G1Affine::identity();
|
||||||
let z2 = E::G2Affine::identity().prepare();
|
let z2 = E::G2Affine::identity().into();
|
||||||
|
|
||||||
let a = E::G1::random(&mut rng).to_affine();
|
let a = E::G1::random(&mut rng).to_affine();
|
||||||
let b = E::G2::random(&mut rng).to_affine().prepare();
|
let b = E::G2::random(&mut rng).to_affine().into();
|
||||||
let c = E::G1::random(&mut rng).to_affine();
|
let c = E::G1::random(&mut rng).to_affine();
|
||||||
let d = E::G2::random(&mut rng).to_affine().prepare();
|
let d = E::G2::random(&mut rng).to_affine().into();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
E::Gt::one(),
|
E::Gt::one(),
|
||||||
|
@ -68,7 +68,7 @@ fn random_miller_loop_tests<E: MultiMillerLoop>() {
|
||||||
let p2 = E::pairing(&a, &b);
|
let p2 = E::pairing(&a, &b);
|
||||||
|
|
||||||
let a = a;
|
let a = a;
|
||||||
let b = b.prepare();
|
let b = b.into();
|
||||||
|
|
||||||
let p1 = E::multi_miller_loop(&[(&a, &b)]).final_exponentiation();
|
let p1 = E::multi_miller_loop(&[(&a, &b)]).final_exponentiation();
|
||||||
|
|
||||||
|
@ -89,9 +89,9 @@ fn random_miller_loop_tests<E: MultiMillerLoop>() {
|
||||||
abcd.mul_assign(&cd);
|
abcd.mul_assign(&cd);
|
||||||
|
|
||||||
let a = a;
|
let a = a;
|
||||||
let b = b.prepare();
|
let b = b.into();
|
||||||
let c = c;
|
let c = c;
|
||||||
let d = d.prepare();
|
let d = d.into();
|
||||||
|
|
||||||
let abcd_with_double_loop =
|
let abcd_with_double_loop =
|
||||||
E::multi_miller_loop(&[(&a, &b), (&c, &d)]).final_exponentiation();
|
E::multi_miller_loop(&[(&a, &b), (&c, &d)]).final_exponentiation();
|
||||||
|
|
Loading…
Reference in New Issue