cyclone_msm/
testing.rs

1//! Generate test instances.
2
3use crate::{
4    bls12_377::G1PTEAffine, preprocess::preprocess_points, timing::timed, Digit, Fr, Scalar,
5};
6use ark_bls12_377::{G1Affine, G1Projective};
7use ark_ec::AffineRepr as _;
8
9pub fn random_digits(size: u8) -> Vec<Digit> {
10    use rand_core::{RngCore, SeedableRng};
11    let mut rng = rand::prelude::StdRng::from_entropy();
12
13    (0..(1 << size)).map(|_| rng.next_u32() as i16).collect()
14}
15
16pub fn random_fr(size: u8) -> Vec<Fr> {
17    use ark_std::UniformRand;
18    use rand_core::SeedableRng;
19    let mut rng = rand::prelude::StdRng::from_entropy();
20
21    (0..(1 << size)).map(|_| Fr::rand(&mut rng)).collect()
22}
23
24pub fn random_points(size: u8) -> Vec<G1Affine> {
25    use rand_core::SeedableRng;
26    let mut rng = rand::prelude::StdRng::from_entropy();
27
28    use ark_std::UniformRand;
29    let points: Vec<_> = timed("generating random projective points", || {
30        (0..(1 << size))
31            .map(|_| G1Projective::rand(&mut rng))
32            .collect()
33    });
34
35    use ark_ec::CurveGroup as _;
36    timed("batch converting to affine", || {
37        G1Projective::normalize_batch(&points)
38    })
39}
40pub fn random_scalars(size: u8) -> Vec<Scalar> {
41    use rand_core::{RngCore, SeedableRng};
42    let mut rng = rand::prelude::StdRng::from_entropy();
43
44    (0..(1 << size))
45        .map(|_| {
46            let mut scalar = Scalar::default();
47            for limb in scalar.iter_mut() {
48                *limb = rng.next_u64();
49            }
50            scalar
51        })
52        .collect()
53}
54
55pub fn zero_scalars(size: u8) -> Vec<Scalar> {
56    (0..(1 << size))
57        .map(|_| {
58            let mut scalar = Scalar::default();
59            for limb in scalar.iter_mut() {
60                *limb = 0;
61            }
62            scalar
63        })
64        .collect()
65}
66
67pub fn noconflict_scalars(size: u8) -> Vec<Scalar> {
68    (0..(1 << size))
69        .map(|i| {
70            let mut scalar = Scalar::default();
71            for limb in scalar.iter_mut() {
72                let i = (i as u16 % 1024) as u64;
73                *limb = (i << 48) | (i << 32) | (i << 16) | i
74            }
75            scalar
76        })
77        .collect()
78}
79
80/// Generates points of the form {P_i} = {\beta^i * g}, where g = basepoint
81pub fn harness_points(size: u8) -> (Fr, Vec<G1PTEAffine>) {
82    use rand_core::SeedableRng;
83    let length = 1 << size;
84
85    use ark_std::{One, UniformRand};
86    let mut rng = rand::prelude::StdRng::from_entropy();
87
88    let beta = Fr::rand(&mut rng);
89    eprintln!("using beta: {}", beta);
90
91    let scalars = timed("scalar gen", || {
92        let mut scalars = Vec::with_capacity(length as _);
93        scalars.push(Fr::one());
94        scalars.push(beta);
95        let mut last = beta;
96        for _ in 2..length {
97            last *= beta;
98            scalars.push(last);
99        }
100        scalars
101    });
102
103    use ark_ec::scalar_mul::fixed_base::FixedBase;
104
105    let points = timed("point gen", || {
106        let scalar_bits = 256;
107        let g = G1Affine::generator();
108        let window = FixedBase::get_mul_window_size(length);
109        let table = FixedBase::get_window_table::<G1Projective>(scalar_bits, window, g.into());
110        FixedBase::msm::<G1Projective>(scalar_bits, window, &table, &scalars)
111    });
112
113    use ark_ec::CurveGroup as _;
114    let points = timed("Projective -> Affine", || {
115        G1Projective::normalize_batch(&points)
116    });
117
118    // the slow part
119    (
120        beta,
121        timed("Affine -> PTEAffine", || preprocess_points(&points)),
122    )
123}
124
125pub fn harness_fr(beta: &Fr, size: u8) -> (Vec<Fr>, G1Projective) {
126    use ark_std::{One, Zero};
127
128    let g = G1Affine::generator();
129
130    let scalars = random_fr(size as u8);
131
132    // calculate expected result "in the exponent"
133    // \Sum_i (scalar_i * beta^i)
134    let result = timed("SW MSM via betas", || {
135        let mut beta_i = Fr::one();
136        let mut prod = Fr::zero();
137        for &scalar in &scalars {
138            prod += scalar * beta_i;
139            beta_i *= beta;
140        }
141        g * prod
142    });
143
144    (scalars, result)
145}
146
147pub fn harness_bigints(beta: &Fr, size: u8) -> (Vec<ark_ff::BigInt<4>>, G1Projective) {
148    use ark_std::{One, Zero};
149
150    use ark_ff::PrimeField;
151    let g = G1Affine::generator();
152
153    let scalars = random_fr(size as u8);
154
155    // calculate expected result "in the exponent"
156    // \Sum_i (scalar_i * beta^i)
157    let result = timed("SW MSM via betas", || {
158        let mut beta_i = Fr::one();
159        let mut prod = Fr::zero();
160        for &scalar in &scalars {
161            prod += scalar * beta_i;
162            beta_i *= beta;
163        }
164        g * prod
165    });
166
167    let scalars: Vec<_> = scalars.iter().map(|scalar| scalar.into_bigint()).collect();
168
169    (scalars, result)
170}
171
172pub fn harness_scalars(beta: &Fr, size: u8) -> (Vec<Scalar>, G1Projective) {
173    use ark_std::{One, Zero};
174
175    use ark_ff::PrimeField;
176    let g = G1Affine::generator();
177
178    let scalars = random_fr(size as u8);
179
180    // calculate expected result "in the exponent"
181    // \Sum_i (scalar_i * beta^i)
182    let result = timed("SW MSM via betas", || {
183        let mut beta_i = Fr::one();
184        let mut prod = Fr::zero();
185        for &scalar in &scalars {
186            prod += scalar * beta_i;
187            beta_i *= beta;
188        }
189        g * prod
190    });
191
192    let scalars: Vec<Scalar> = scalars
193        .iter()
194        .map(|scalar| scalar.into_bigint().0)
195        .collect();
196
197    (scalars, result)
198}
199
200pub fn digits_to_scalars(digits: &[Digit]) -> Vec<Fr> {
201    digits
202        .iter()
203        .copied()
204        .map(|digit| {
205            if digit >= 0 {
206                Fr::from(digit as u16)
207            } else {
208                -Fr::from((-(digit as i32)) as u16)
209            }
210        })
211        .collect()
212}
213
214pub fn harness_digits(beta: &Fr, size: u8) -> (Vec<i16>, G1Projective) {
215    use ark_std::{One, Zero};
216
217    // use our_ec::AffineCurve;
218    let g = G1Affine::generator();
219
220    let digits = random_digits(size as u8);
221    let scalars = digits_to_scalars(&digits);
222
223    // calculate expected result "in the exponent"
224    // \Sum_i (scalar_i * beta^i)
225    let result = timed("SW MSM via betas", || {
226        let mut beta_i = Fr::one();
227        let mut prod = Fr::zero();
228        for &scalar in &scalars {
229            prod += scalar * beta_i;
230            beta_i *= beta;
231        }
232        g * prod
233    });
234
235    (digits, result)
236}
237
238pub fn noconflict_digits(size: u8) -> Vec<i16> {
239    (0..(1usize << size)).map(|i| (i % 1024) as i16).collect()
240}
241
242/// "Fast" calculation of MSM in SW via MSM of the scalars.
243pub fn harness_digits_conflictfree(beta: &Fr, size: usize) -> (Vec<i16>, G1Projective) {
244    use ark_std::{One, Zero};
245
246    // use our_ec::AffineCurve;
247    let g = G1Affine::generator();
248
249    let digits = noconflict_digits(size as u8);
250    let scalars = digits_to_scalars(&digits);
251
252    // calculate expected result "in the exponent"
253    let result = timed("SW MSM via betas", || {
254        let mut beta_i = Fr::one();
255        let mut prod = Fr::zero();
256        for &scalar in &scalars {
257            prod += scalar * beta_i;
258            beta_i *= beta;
259        }
260        g * prod
261    });
262
263    (digits, result)
264}