/rust/registry/src/index.crates.io-1949cf8c6b5b557f/group-0.13.0/src/wnaf.rs
Line | Count | Source |
1 | | use alloc::vec::Vec; |
2 | | use core::iter; |
3 | | use core::marker::PhantomData; |
4 | | use core::ops::Mul; |
5 | | |
6 | | use ff::PrimeField; |
7 | | |
8 | | use super::Group; |
9 | | |
10 | | /// Extension trait on a [`Group`] that provides helpers used by [`Wnaf`]. |
11 | | pub trait WnafGroup: Group { |
12 | | /// Recommends a wNAF window size given the number of scalars you intend to multiply |
13 | | /// a base by. Always returns a number between 2 and 22, inclusive. |
14 | | fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize; |
15 | | } |
16 | | |
17 | | /// Replaces the contents of `table` with a w-NAF window table for the given window size. |
18 | 0 | pub(crate) fn wnaf_table<G: Group>(table: &mut Vec<G>, mut base: G, window: usize) { |
19 | 0 | table.truncate(0); |
20 | 0 | table.reserve(1 << (window - 1)); |
21 | | |
22 | 0 | let dbl = base.double(); |
23 | | |
24 | 0 | for _ in 0..(1 << (window - 1)) { |
25 | 0 | table.push(base); |
26 | 0 | base.add_assign(&dbl); |
27 | 0 | } |
28 | 0 | } |
29 | | |
30 | | /// This struct represents a view of a sequence of bytes as a sequence of |
31 | | /// `u64` limbs in little-endian byte order. It maintains a current index, and |
32 | | /// allows access to the limb at that index and the one following it. Bytes |
33 | | /// beyond the end of the original buffer are treated as zero. |
34 | | struct LimbBuffer<'a> { |
35 | | buf: &'a [u8], |
36 | | cur_idx: usize, |
37 | | cur_limb: u64, |
38 | | next_limb: u64, |
39 | | } |
40 | | |
41 | | impl<'a> LimbBuffer<'a> { |
42 | 0 | fn new(buf: &'a [u8]) -> Self { |
43 | 0 | let mut ret = Self { |
44 | 0 | buf, |
45 | 0 | cur_idx: 0, |
46 | 0 | cur_limb: 0, |
47 | 0 | next_limb: 0, |
48 | 0 | }; |
49 | | |
50 | | // Initialise the limb buffers. |
51 | 0 | ret.increment_limb(); |
52 | 0 | ret.increment_limb(); |
53 | 0 | ret.cur_idx = 0usize; |
54 | | |
55 | 0 | ret |
56 | 0 | } |
57 | | |
58 | 0 | fn increment_limb(&mut self) { |
59 | 0 | self.cur_idx += 1; |
60 | 0 | self.cur_limb = self.next_limb; |
61 | 0 | match self.buf.len() { |
62 | | // There are no more bytes in the buffer; zero-extend. |
63 | 0 | 0 => self.next_limb = 0, |
64 | | |
65 | | // There are fewer bytes in the buffer than a u64 limb; zero-extend. |
66 | 0 | x @ 1..=7 => { |
67 | 0 | let mut next_limb = [0; 8]; |
68 | 0 | next_limb[..x].copy_from_slice(self.buf); |
69 | 0 | self.next_limb = u64::from_le_bytes(next_limb); |
70 | 0 | self.buf = &[]; |
71 | 0 | } |
72 | | |
73 | | // There are at least eight bytes in the buffer; read the next u64 limb. |
74 | 0 | _ => { |
75 | 0 | let (next_limb, rest) = self.buf.split_at(8); |
76 | 0 | self.next_limb = u64::from_le_bytes(next_limb.try_into().unwrap()); |
77 | 0 | self.buf = rest; |
78 | 0 | } |
79 | | } |
80 | 0 | } |
81 | | |
82 | 0 | fn get(&mut self, idx: usize) -> (u64, u64) { |
83 | 0 | assert!([self.cur_idx, self.cur_idx + 1].contains(&idx)); |
84 | 0 | if idx > self.cur_idx { |
85 | 0 | self.increment_limb(); |
86 | 0 | } |
87 | 0 | (self.cur_limb, self.next_limb) |
88 | 0 | } |
89 | | } |
90 | | |
91 | | /// Replaces the contents of `wnaf` with the w-NAF representation of a little-endian |
92 | | /// scalar. |
93 | 0 | pub(crate) fn wnaf_form<S: AsRef<[u8]>>(wnaf: &mut Vec<i64>, c: S, window: usize) { |
94 | | // Required by the NAF definition |
95 | 0 | debug_assert!(window >= 2); |
96 | | // Required so that the NAF digits fit in i64 |
97 | 0 | debug_assert!(window <= 64); |
98 | | |
99 | 0 | let bit_len = c.as_ref().len() * 8; |
100 | | |
101 | 0 | wnaf.truncate(0); |
102 | 0 | wnaf.reserve(bit_len); |
103 | | |
104 | | // Initialise the current and next limb buffers. |
105 | 0 | let mut limbs = LimbBuffer::new(c.as_ref()); |
106 | | |
107 | 0 | let width = 1u64 << window; |
108 | 0 | let window_mask = width - 1; |
109 | | |
110 | 0 | let mut pos = 0; |
111 | 0 | let mut carry = 0; |
112 | 0 | while pos < bit_len { |
113 | | // Construct a buffer of bits of the scalar, starting at bit `pos` |
114 | 0 | let u64_idx = pos / 64; |
115 | 0 | let bit_idx = pos % 64; |
116 | 0 | let (cur_u64, next_u64) = limbs.get(u64_idx); |
117 | 0 | let bit_buf = if bit_idx + window < 64 { |
118 | | // This window's bits are contained in a single u64 |
119 | 0 | cur_u64 >> bit_idx |
120 | | } else { |
121 | | // Combine the current u64's bits with the bits from the next u64 |
122 | 0 | (cur_u64 >> bit_idx) | (next_u64 << (64 - bit_idx)) |
123 | | }; |
124 | | |
125 | | // Add the carry into the current window |
126 | 0 | let window_val = carry + (bit_buf & window_mask); |
127 | | |
128 | 0 | if window_val & 1 == 0 { |
129 | 0 | // If the window value is even, preserve the carry and emit 0. |
130 | 0 | // Why is the carry preserved? |
131 | 0 | // If carry == 0 and window_val & 1 == 0, then the next carry should be 0 |
132 | 0 | // If carry == 1 and window_val & 1 == 0, then bit_buf & 1 == 1 so the next carry should be 1 |
133 | 0 | wnaf.push(0); |
134 | 0 | pos += 1; |
135 | 0 | } else { |
136 | 0 | wnaf.push(if window_val < width / 2 { |
137 | 0 | carry = 0; |
138 | 0 | window_val as i64 |
139 | | } else { |
140 | 0 | carry = 1; |
141 | 0 | (window_val as i64).wrapping_sub(width as i64) |
142 | | }); |
143 | 0 | wnaf.extend(iter::repeat(0).take(window - 1)); |
144 | 0 | pos += window; |
145 | | } |
146 | | } |
147 | 0 | } |
148 | | |
149 | | /// Performs w-NAF exponentiation with the provided window table and w-NAF form scalar. |
150 | | /// |
151 | | /// This function must be provided a `table` and `wnaf` that were constructed with |
152 | | /// the same window size; otherwise, it may panic or produce invalid results. |
153 | 0 | pub(crate) fn wnaf_exp<G: Group>(table: &[G], wnaf: &[i64]) -> G { |
154 | 0 | let mut result = G::identity(); |
155 | | |
156 | 0 | let mut found_one = false; |
157 | | |
158 | 0 | for n in wnaf.iter().rev() { |
159 | 0 | if found_one { |
160 | 0 | result = result.double(); |
161 | 0 | } |
162 | | |
163 | 0 | if *n != 0 { |
164 | 0 | found_one = true; |
165 | | |
166 | 0 | if *n > 0 { |
167 | 0 | result += &table[(n / 2) as usize]; |
168 | 0 | } else { |
169 | 0 | result -= &table[((-n) / 2) as usize]; |
170 | 0 | } |
171 | 0 | } |
172 | | } |
173 | | |
174 | 0 | result |
175 | 0 | } |
176 | | |
177 | | /// A "w-ary non-adjacent form" scalar multiplication (also known as exponentiation) |
178 | | /// context. |
179 | | /// |
180 | | /// # Examples |
181 | | /// |
182 | | /// This struct can be used to implement several patterns: |
183 | | /// |
184 | | /// ## One base, one scalar |
185 | | /// |
186 | | /// For this pattern, you can use a transient `Wnaf` context: |
187 | | /// |
188 | | /// ```ignore |
189 | | /// use group::Wnaf; |
190 | | /// |
191 | | /// let result = Wnaf::new().scalar(&scalar).base(base); |
192 | | /// ``` |
193 | | /// |
194 | | /// ## Many bases, one scalar |
195 | | /// |
196 | | /// For this pattern, you create a `Wnaf` context, load the scalar into it, and then |
197 | | /// process each base in turn: |
198 | | /// |
199 | | /// ```ignore |
200 | | /// use group::Wnaf; |
201 | | /// |
202 | | /// let mut wnaf = Wnaf::new(); |
203 | | /// let mut wnaf_scalar = wnaf.scalar(&scalar); |
204 | | /// let results: Vec<_> = bases |
205 | | /// .into_iter() |
206 | | /// .map(|base| wnaf_scalar.base(base)) |
207 | | /// .collect(); |
208 | | /// ``` |
209 | | /// |
210 | | /// ## One base, many scalars |
211 | | /// |
212 | | /// For this pattern, you create a `Wnaf` context, load the base into it, and then process |
213 | | /// each scalar in turn: |
214 | | /// |
215 | | /// ```ignore |
216 | | /// use group::Wnaf; |
217 | | /// |
218 | | /// let mut wnaf = Wnaf::new(); |
219 | | /// let mut wnaf_base = wnaf.base(base, scalars.len()); |
220 | | /// let results: Vec<_> = scalars |
221 | | /// .iter() |
222 | | /// .map(|scalar| wnaf_base.scalar(scalar)) |
223 | | /// .collect(); |
224 | | /// ``` |
225 | | /// |
226 | | /// ## Many bases, many scalars |
227 | | /// |
228 | | /// Say you have `n` bases and `m` scalars, and want to produce `n * m` results. For this |
229 | | /// pattern, you need to cache the w-NAF tables for the bases and then compute the w-NAF |
230 | | /// form of the scalars on the fly for every base, or vice versa: |
231 | | /// |
232 | | /// ```ignore |
233 | | /// use group::Wnaf; |
234 | | /// |
235 | | /// let mut wnaf_contexts: Vec<_> = (0..bases.len()).map(|_| Wnaf::new()).collect(); |
236 | | /// let mut wnaf_bases: Vec<_> = wnaf_contexts |
237 | | /// .iter_mut() |
238 | | /// .zip(bases) |
239 | | /// .map(|(wnaf, base)| wnaf.base(base, scalars.len())) |
240 | | /// .collect(); |
241 | | /// let results: Vec<_> = wnaf_bases |
242 | | /// .iter() |
243 | | /// .flat_map(|wnaf_base| scalars.iter().map(|scalar| wnaf_base.scalar(scalar))) |
244 | | /// .collect(); |
245 | | /// ``` |
246 | | /// |
247 | | /// Alternatively, use the [`WnafBase`] and [`WnafScalar`] types, which enable the various |
248 | | /// tables and w-NAF forms to be cached individually per base and scalar. These types can |
249 | | /// then be directly multiplied without any additional runtime work, at the cost of fixing |
250 | | /// a specific window size (rather than choosing the window size dynamically). |
251 | | #[derive(Debug)] |
252 | | pub struct Wnaf<W, B, S> { |
253 | | base: B, |
254 | | scalar: S, |
255 | | window_size: W, |
256 | | } |
257 | | |
258 | | impl<G: Group> Wnaf<(), Vec<G>, Vec<i64>> { |
259 | | /// Construct a new wNAF context without allocating. |
260 | 0 | pub fn new() -> Self { |
261 | 0 | Wnaf { |
262 | 0 | base: vec![], |
263 | 0 | scalar: vec![], |
264 | 0 | window_size: (), |
265 | 0 | } |
266 | 0 | } |
267 | | } |
268 | | |
269 | | #[cfg(feature = "wnaf-memuse")] |
270 | | impl<G: Group + memuse::DynamicUsage> memuse::DynamicUsage for Wnaf<(), Vec<G>, Vec<i64>> { |
271 | | fn dynamic_usage(&self) -> usize { |
272 | | self.base.dynamic_usage() + self.scalar.dynamic_usage() |
273 | | } |
274 | | |
275 | | fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) { |
276 | | let (base_lower, base_upper) = self.base.dynamic_usage_bounds(); |
277 | | let (scalar_lower, scalar_upper) = self.scalar.dynamic_usage_bounds(); |
278 | | |
279 | | ( |
280 | | base_lower + scalar_lower, |
281 | | base_upper.zip(scalar_upper).map(|(a, b)| a + b), |
282 | | ) |
283 | | } |
284 | | } |
285 | | |
286 | | impl<G: WnafGroup> Wnaf<(), Vec<G>, Vec<i64>> { |
287 | | /// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that |
288 | | /// can perform exponentiations with `.scalar(..)`. |
289 | 0 | pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf<usize, &[G], &mut Vec<i64>> { |
290 | | // Compute the appropriate window size based on the number of scalars. |
291 | 0 | let window_size = G::recommended_wnaf_for_num_scalars(num_scalars); |
292 | | |
293 | | // Compute a wNAF table for the provided base and window size. |
294 | 0 | wnaf_table(&mut self.base, base, window_size); |
295 | | |
296 | | // Return a Wnaf object that immutably borrows the computed base storage location, |
297 | | // but mutably borrows the scalar storage location. |
298 | 0 | Wnaf { |
299 | 0 | base: &self.base[..], |
300 | 0 | scalar: &mut self.scalar, |
301 | 0 | window_size, |
302 | 0 | } |
303 | 0 | } |
304 | | |
305 | | /// Given a scalar, compute its wNAF representation and return a `Wnaf` object that can perform |
306 | | /// exponentiations with `.base(..)`. |
307 | 0 | pub fn scalar(&mut self, scalar: &<G as Group>::Scalar) -> Wnaf<usize, &mut Vec<G>, &[i64]> { |
308 | | // We hard-code a window size of 4. |
309 | 0 | let window_size = 4; |
310 | | |
311 | | // Compute the wNAF form of the scalar. |
312 | 0 | wnaf_form(&mut self.scalar, scalar.to_repr(), window_size); |
313 | | |
314 | | // Return a Wnaf object that mutably borrows the base storage location, but |
315 | | // immutably borrows the computed wNAF form scalar location. |
316 | 0 | Wnaf { |
317 | 0 | base: &mut self.base, |
318 | 0 | scalar: &self.scalar[..], |
319 | 0 | window_size, |
320 | 0 | } |
321 | 0 | } |
322 | | } |
323 | | |
324 | | impl<'a, G: Group> Wnaf<usize, &'a [G], &'a mut Vec<i64>> { |
325 | | /// Constructs new space for the scalar representation while borrowing |
326 | | /// the computed window table, for sending the window table across threads. |
327 | 0 | pub fn shared(&self) -> Wnaf<usize, &'a [G], Vec<i64>> { |
328 | 0 | Wnaf { |
329 | 0 | base: self.base, |
330 | 0 | scalar: vec![], |
331 | 0 | window_size: self.window_size, |
332 | 0 | } |
333 | 0 | } |
334 | | } |
335 | | |
336 | | #[cfg(feature = "wnaf-memuse")] |
337 | | impl<'a, G: Group> memuse::DynamicUsage for Wnaf<usize, &'a [G], Vec<i64>> { |
338 | | fn dynamic_usage(&self) -> usize { |
339 | | // The heap memory for the window table is counted in the parent `Wnaf`. |
340 | | self.scalar.dynamic_usage() |
341 | | } |
342 | | |
343 | | fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) { |
344 | | self.scalar.dynamic_usage_bounds() |
345 | | } |
346 | | } |
347 | | |
348 | | impl<'a, G: Group> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> { |
349 | | /// Constructs new space for the window table while borrowing |
350 | | /// the computed scalar representation, for sending the scalar representation |
351 | | /// across threads. |
352 | 0 | pub fn shared(&self) -> Wnaf<usize, Vec<G>, &'a [i64]> { |
353 | 0 | Wnaf { |
354 | 0 | base: vec![], |
355 | 0 | scalar: self.scalar, |
356 | 0 | window_size: self.window_size, |
357 | 0 | } |
358 | 0 | } |
359 | | } |
360 | | |
361 | | #[cfg(feature = "wnaf-memuse")] |
362 | | impl<'a, G: Group + memuse::DynamicUsage> memuse::DynamicUsage for Wnaf<usize, Vec<G>, &'a [i64]> { |
363 | | fn dynamic_usage(&self) -> usize { |
364 | | // The heap memory for the scalar representation is counted in the parent `Wnaf`. |
365 | | self.base.dynamic_usage() |
366 | | } |
367 | | |
368 | | fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) { |
369 | | self.base.dynamic_usage_bounds() |
370 | | } |
371 | | } |
372 | | |
373 | | impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> { |
374 | | /// Performs exponentiation given a base. |
375 | 0 | pub fn base<G: Group>(&mut self, base: G) -> G |
376 | 0 | where |
377 | 0 | B: AsMut<Vec<G>>, |
378 | | { |
379 | 0 | wnaf_table(self.base.as_mut(), base, self.window_size); |
380 | 0 | wnaf_exp(self.base.as_mut(), self.scalar.as_ref()) |
381 | 0 | } |
382 | | } |
383 | | |
384 | | impl<B, S: AsMut<Vec<i64>>> Wnaf<usize, B, S> { |
385 | | /// Performs exponentiation given a scalar. |
386 | 0 | pub fn scalar<G: Group>(&mut self, scalar: &<G as Group>::Scalar) -> G |
387 | 0 | where |
388 | 0 | B: AsRef<[G]>, |
389 | | { |
390 | 0 | wnaf_form(self.scalar.as_mut(), scalar.to_repr(), self.window_size); |
391 | 0 | wnaf_exp(self.base.as_ref(), self.scalar.as_mut()) |
392 | 0 | } |
393 | | } |
394 | | |
395 | | /// A "w-ary non-adjacent form" scalar, that uses precomputation to improve the speed of |
396 | | /// scalar multiplication. |
397 | | /// |
398 | | /// # Examples |
399 | | /// |
400 | | /// See [`WnafBase`] for usage examples. |
401 | | #[derive(Clone, Debug)] |
402 | | pub struct WnafScalar<F: PrimeField, const WINDOW_SIZE: usize> { |
403 | | wnaf: Vec<i64>, |
404 | | field: PhantomData<F>, |
405 | | } |
406 | | |
407 | | #[cfg(feature = "wnaf-memuse")] |
408 | | impl<F: PrimeField, const WINDOW_SIZE: usize> memuse::DynamicUsage for WnafScalar<F, WINDOW_SIZE> { |
409 | | fn dynamic_usage(&self) -> usize { |
410 | | self.wnaf.dynamic_usage() |
411 | | } |
412 | | |
413 | | fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) { |
414 | | self.wnaf.dynamic_usage_bounds() |
415 | | } |
416 | | } |
417 | | |
418 | | impl<F: PrimeField, const WINDOW_SIZE: usize> WnafScalar<F, WINDOW_SIZE> { |
419 | | /// Computes the w-NAF representation of the given scalar with the specified |
420 | | /// `WINDOW_SIZE`. |
421 | 0 | pub fn new(scalar: &F) -> Self { |
422 | 0 | let mut wnaf = vec![]; |
423 | | |
424 | | // Compute the w-NAF form of the scalar. |
425 | 0 | wnaf_form(&mut wnaf, scalar.to_repr(), WINDOW_SIZE); |
426 | | |
427 | 0 | WnafScalar { |
428 | 0 | wnaf, |
429 | 0 | field: PhantomData::default(), |
430 | 0 | } |
431 | 0 | } |
432 | | } |
433 | | |
434 | | /// A fixed window table for a group element, precomputed to improve the speed of scalar |
435 | | /// multiplication. |
436 | | /// |
437 | | /// This struct is designed for usage patterns that have long-term cached bases and/or |
438 | | /// scalars, or [Cartesian products] of bases and scalars. The [`Wnaf`] API enables one or |
439 | | /// the other to be cached, but requires either the base window tables or the scalar w-NAF |
440 | | /// forms to be computed repeatedly on the fly, which can become a significant performance |
441 | | /// issue for some use cases. |
442 | | /// |
443 | | /// `WnafBase` and [`WnafScalar`] enable an alternative trade-off: by fixing the window |
444 | | /// size at compile time, the precomputations are guaranteed to only occur once per base |
445 | | /// and once per scalar. Users should select their window size based on how long the bases |
446 | | /// are expected to live; a larger window size will consume more memory and take longer to |
447 | | /// precompute, but result in faster scalar multiplications. |
448 | | /// |
449 | | /// [Cartesian products]: https://en.wikipedia.org/wiki/Cartesian_product |
450 | | /// |
451 | | /// # Examples |
452 | | /// |
453 | | /// ```ignore |
454 | | /// use group::{WnafBase, WnafScalar}; |
455 | | /// |
456 | | /// let wnaf_bases: Vec<_> = bases.into_iter().map(WnafBase::<_, 4>::new).collect(); |
457 | | /// let wnaf_scalars: Vec<_> = scalars.iter().map(WnafScalar::new).collect(); |
458 | | /// let results: Vec<_> = wnaf_bases |
459 | | /// .iter() |
460 | | /// .flat_map(|base| wnaf_scalars.iter().map(|scalar| base * scalar)) |
461 | | /// .collect(); |
462 | | /// ``` |
463 | | /// |
464 | | /// Note that this pattern requires specifying a fixed window size (unlike previous |
465 | | /// patterns that picked a suitable window size internally). This is necessary to ensure |
466 | | /// in the type system that the base and scalar `Wnaf`s were computed with the same window |
467 | | /// size, allowing the result to be computed infallibly. |
468 | | #[derive(Clone, Debug)] |
469 | | pub struct WnafBase<G: Group, const WINDOW_SIZE: usize> { |
470 | | table: Vec<G>, |
471 | | } |
472 | | |
473 | | #[cfg(feature = "wnaf-memuse")] |
474 | | impl<G: Group + memuse::DynamicUsage, const WINDOW_SIZE: usize> memuse::DynamicUsage |
475 | | for WnafBase<G, WINDOW_SIZE> |
476 | | { |
477 | | fn dynamic_usage(&self) -> usize { |
478 | | self.table.dynamic_usage() |
479 | | } |
480 | | |
481 | | fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) { |
482 | | self.table.dynamic_usage_bounds() |
483 | | } |
484 | | } |
485 | | |
486 | | impl<G: Group, const WINDOW_SIZE: usize> WnafBase<G, WINDOW_SIZE> { |
487 | | /// Computes a window table for the given base with the specified `WINDOW_SIZE`. |
488 | 0 | pub fn new(base: G) -> Self { |
489 | 0 | let mut table = vec![]; |
490 | | |
491 | | // Compute a window table for the provided base and window size. |
492 | 0 | wnaf_table(&mut table, base, WINDOW_SIZE); |
493 | | |
494 | 0 | WnafBase { table } |
495 | 0 | } |
496 | | } |
497 | | |
498 | | impl<G: Group, const WINDOW_SIZE: usize> Mul<&WnafScalar<G::Scalar, WINDOW_SIZE>> |
499 | | for &WnafBase<G, WINDOW_SIZE> |
500 | | { |
501 | | type Output = G; |
502 | | |
503 | 0 | fn mul(self, rhs: &WnafScalar<G::Scalar, WINDOW_SIZE>) -> Self::Output { |
504 | 0 | wnaf_exp(&self.table, &rhs.wnaf) |
505 | 0 | } |
506 | | } |