1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use dusk_bls12_381::{G1Affine, G1Projective, G2Affine, G2Projective, Scalar};
use rand_core::RngCore;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
pub(crate) fn powers_of(scalar: &Scalar, max_degree: usize) -> Vec<Scalar> {
let mut powers = Vec::with_capacity(max_degree + 1);
powers.push(Scalar::one());
for i in 1..=max_degree {
powers.push(powers[i - 1] * scalar);
}
powers
}
pub(crate) fn random_scalar<R: RngCore>(rng: &mut R) -> Scalar {
Scalar::from_raw([
rng.next_u64(),
rng.next_u64(),
rng.next_u64(),
rng.next_u64(),
])
}
pub(crate) fn random_g1_point<R: RngCore>(rng: &mut R) -> G1Projective {
G1Affine::generator() * random_scalar(rng)
}
pub(crate) fn random_g2_point<R: RngCore>(rng: &mut R) -> G2Projective {
G2Affine::generator() * random_scalar(rng)
}
pub(crate) fn slow_multiscalar_mul_single_base(
scalars: &[Scalar],
base: G1Projective,
) -> Vec<G1Projective> {
scalars.par_iter().map(|s| base * *s).collect()
}
use std::ops::MulAssign;
pub fn batch_inversion(v: &mut [Scalar]) {
let mut prod = Vec::with_capacity(v.len());
let mut tmp = Scalar::one();
for f in v.iter().filter(|f| f != &&Scalar::zero()) {
tmp.mul_assign(f);
prod.push(tmp);
}
tmp = tmp.invert().unwrap();
for (f, s) in v
.iter_mut()
.rev()
.filter(|f| f != &&Scalar::zero())
.zip(prod.into_iter().rev().skip(1).chain(Some(Scalar::one())))
{
let new_tmp = tmp * *f;
*f = tmp * s;
tmp = new_tmp;
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_batch_inversion() {
let one = Scalar::from(1);
let two = Scalar::from(2);
let three = Scalar::from(3);
let four = Scalar::from(4);
let five = Scalar::from(5);
let original_scalars = vec![one, two, three, four, five];
let mut inverted_scalars = vec![one, two, three, four, five];
batch_inversion(&mut inverted_scalars);
for (x, x_inv) in original_scalars.iter().zip(inverted_scalars.iter()) {
assert_eq!(x.invert().unwrap(), *x_inv);
}
}
}