diff --git a/src/groth16/prover.rs b/src/groth16/prover.rs index 11831f7..a2a6f46 100644 --- a/src/groth16/prover.rs +++ b/src/groth16/prover.rs @@ -229,14 +229,26 @@ where let a_len = a.len() - 1; a.truncate(a_len); // TODO: parallelize if it's even helpful - let a = Arc::new(a.into_iter().map(|s| s.0).collect::>()); + let a = Arc::new(a.into_iter().map(|s| s.0.to_le_bits()).collect::>()); multiexp(&worker, params.get_h(a.len())?, FullDensity, a) }; // TODO: parallelize if it's even helpful - let input_assignment = Arc::new(prover.input_assignment); - let aux_assignment = Arc::new(prover.aux_assignment); + let input_assignment = Arc::new( + prover + .input_assignment + .into_iter() + .map(|s| s.to_le_bits()) + .collect::>(), + ); + let aux_assignment = Arc::new( + prover + .aux_assignment + .into_iter() + .map(|s| s.to_le_bits()) + .collect::>(), + ); let l = multiexp( &worker, diff --git a/src/multiexp.rs b/src/multiexp.rs index d6fb129..fd138e5 100644 --- a/src/multiexp.rs +++ b/src/multiexp.rs @@ -1,6 +1,7 @@ use super::multicore::Worker; use bit_vec::{self, BitVec}; -use ff::{Field, PrimeField}; +use bitvec::{array::BitArray, order::Lsb0}; +use ff::PrimeField; use futures::Future; use group::prime::{PrimeCurve, PrimeCurveAffine}; use std::io; @@ -154,7 +155,7 @@ fn multiexp_inner( pool: &Worker, bases: S, density_map: D, - exponents: Arc>, + exponents: Arc::ReprBits>>>, mut skip: u32, c: u32, handle_trivial: bool, @@ -181,22 +182,24 @@ where // Create space for the buckets let mut buckets = vec![G::identity(); (1 << c) - 1]; - let one = G::Scalar::one(); - // 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 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)?; - } else if exp == one { + } else if exp_is_one { if handle_trivial { acc.add_assign_from_source(&mut bases)?; } else { bases.skip(1)?; } } else { - let exp = exp.to_le_bits(); - let exp = exp .into_iter() .skip(skip as usize) @@ -266,7 +269,7 @@ pub fn multiexp( pool: &Worker, bases: S, density_map: D, - exponents: Arc>, + exponents: Arc::ReprBits>>>, ) -> Box> where for<'a> &'a Q: QueryDensity, @@ -309,6 +312,7 @@ fn test_with_bls12() { } use bls12_381::{Bls12, Scalar}; + use ff::Field; use group::{Curve, Group}; use pairing::Engine; use rand; @@ -321,6 +325,7 @@ fn test_with_bls12() { .map(|_| Scalar::random(&mut rng)) .collect::>(), ); + let v_bits = Arc::new(v.iter().map(|e| e.to_le_bits()).collect::>()); let g = Arc::new( (0..SAMPLES) .map(|_| ::G1::random(&mut rng).to_affine()) @@ -331,7 +336,7 @@ fn test_with_bls12() { 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); }