Pass exponent bits into multiexp instead of exponents themselves
This de-duplicates multiple Montgomery reductions.
This commit is contained in:
parent
f90fa65a32
commit
e6a404a29e
|
@ -229,14 +229,26 @@ where
|
||||||
let a_len = a.len() - 1;
|
let a_len = a.len() - 1;
|
||||||
a.truncate(a_len);
|
a.truncate(a_len);
|
||||||
// TODO: parallelize if it's even helpful
|
// TODO: parallelize if it's even helpful
|
||||||
let a = Arc::new(a.into_iter().map(|s| s.0).collect::<Vec<_>>());
|
let a = Arc::new(a.into_iter().map(|s| s.0.to_le_bits()).collect::<Vec<_>>());
|
||||||
|
|
||||||
multiexp(&worker, params.get_h(a.len())?, FullDensity, a)
|
multiexp(&worker, params.get_h(a.len())?, FullDensity, a)
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: parallelize if it's even helpful
|
// TODO: parallelize if it's even helpful
|
||||||
let input_assignment = Arc::new(prover.input_assignment);
|
let input_assignment = Arc::new(
|
||||||
let aux_assignment = Arc::new(prover.aux_assignment);
|
prover
|
||||||
|
.input_assignment
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.to_le_bits())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
let aux_assignment = Arc::new(
|
||||||
|
prover
|
||||||
|
.aux_assignment
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.to_le_bits())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
|
||||||
let l = multiexp(
|
let l = multiexp(
|
||||||
&worker,
|
&worker,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use super::multicore::Worker;
|
use super::multicore::Worker;
|
||||||
use bit_vec::{self, BitVec};
|
use bit_vec::{self, BitVec};
|
||||||
use ff::{Field, PrimeField};
|
use bitvec::{array::BitArray, order::Lsb0};
|
||||||
|
use ff::PrimeField;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use group::prime::{PrimeCurve, PrimeCurveAffine};
|
use group::prime::{PrimeCurve, PrimeCurveAffine};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -154,7 +155,7 @@ fn multiexp_inner<Q, D, G, S>(
|
||||||
pool: &Worker,
|
pool: &Worker,
|
||||||
bases: S,
|
bases: S,
|
||||||
density_map: D,
|
density_map: D,
|
||||||
exponents: Arc<Vec<G::Scalar>>,
|
exponents: Arc<Vec<BitArray<Lsb0, <G::Scalar as PrimeField>::ReprBits>>>,
|
||||||
mut skip: u32,
|
mut skip: u32,
|
||||||
c: u32,
|
c: u32,
|
||||||
handle_trivial: bool,
|
handle_trivial: bool,
|
||||||
|
@ -181,22 +182,24 @@ where
|
||||||
// Create space for the buckets
|
// Create space for the buckets
|
||||||
let mut buckets = vec![G::identity(); (1 << c) - 1];
|
let mut buckets = vec![G::identity(); (1 << c) - 1];
|
||||||
|
|
||||||
let one = G::Scalar::one();
|
|
||||||
|
|
||||||
// Sort the bases into buckets
|
// Sort the bases into buckets
|
||||||
for (&exp, density) in exponents.iter().zip(density_map.as_ref().iter()) {
|
for (exp, density) in exponents.iter().zip(density_map.as_ref().iter()) {
|
||||||
if density {
|
if density {
|
||||||
if exp.is_zero() {
|
let (exp_is_zero, exp_is_one) = {
|
||||||
|
let (first, rest) = exp.split_first().unwrap();
|
||||||
|
let rest_unset = rest.not_any();
|
||||||
|
(!*first && rest_unset, *first && rest_unset)
|
||||||
|
};
|
||||||
|
|
||||||
|
if exp_is_zero {
|
||||||
bases.skip(1)?;
|
bases.skip(1)?;
|
||||||
} else if exp == one {
|
} else if exp_is_one {
|
||||||
if handle_trivial {
|
if handle_trivial {
|
||||||
acc.add_assign_from_source(&mut bases)?;
|
acc.add_assign_from_source(&mut bases)?;
|
||||||
} else {
|
} else {
|
||||||
bases.skip(1)?;
|
bases.skip(1)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let exp = exp.to_le_bits();
|
|
||||||
|
|
||||||
let exp = exp
|
let exp = exp
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.skip(skip as usize)
|
.skip(skip as usize)
|
||||||
|
@ -266,7 +269,7 @@ pub fn multiexp<Q, D, G, S>(
|
||||||
pool: &Worker,
|
pool: &Worker,
|
||||||
bases: S,
|
bases: S,
|
||||||
density_map: D,
|
density_map: D,
|
||||||
exponents: Arc<Vec<G::Scalar>>,
|
exponents: Arc<Vec<BitArray<Lsb0, <G::Scalar as PrimeField>::ReprBits>>>,
|
||||||
) -> Box<dyn Future<Item = G, Error = SynthesisError>>
|
) -> Box<dyn Future<Item = G, Error = SynthesisError>>
|
||||||
where
|
where
|
||||||
for<'a> &'a Q: QueryDensity,
|
for<'a> &'a Q: QueryDensity,
|
||||||
|
@ -309,6 +312,7 @@ fn test_with_bls12() {
|
||||||
}
|
}
|
||||||
|
|
||||||
use bls12_381::{Bls12, Scalar};
|
use bls12_381::{Bls12, Scalar};
|
||||||
|
use ff::Field;
|
||||||
use group::{Curve, Group};
|
use group::{Curve, Group};
|
||||||
use pairing::Engine;
|
use pairing::Engine;
|
||||||
use rand;
|
use rand;
|
||||||
|
@ -321,6 +325,7 @@ fn test_with_bls12() {
|
||||||
.map(|_| Scalar::random(&mut rng))
|
.map(|_| Scalar::random(&mut rng))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
|
let v_bits = Arc::new(v.iter().map(|e| e.to_le_bits()).collect::<Vec<_>>());
|
||||||
let g = Arc::new(
|
let g = Arc::new(
|
||||||
(0..SAMPLES)
|
(0..SAMPLES)
|
||||||
.map(|_| <Bls12 as Engine>::G1::random(&mut rng).to_affine())
|
.map(|_| <Bls12 as Engine>::G1::random(&mut rng).to_affine())
|
||||||
|
@ -331,7 +336,7 @@ fn test_with_bls12() {
|
||||||
|
|
||||||
let pool = Worker::new();
|
let pool = Worker::new();
|
||||||
|
|
||||||
let fast = multiexp(&pool, (g, 0), FullDensity, v).wait().unwrap();
|
let fast = multiexp(&pool, (g, 0), FullDensity, v_bits).wait().unwrap();
|
||||||
|
|
||||||
assert_eq!(naive, fast);
|
assert_eq!(naive, fast);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue