wnaf/scalar.rs
1use crate::{Digit, WindowSize, WnafSize, le_repr, wnaf_form};
2use array::{Array, typenum::Unsigned};
3use core::marker::PhantomData;
4use ff::PrimeField;
5
6#[cfg(doc)]
7use crate::WnafBase;
8
9/// A "w-ary non-adjacent form" scalar, precomputed to improve the speed of scalar multiplication.
10///
11/// The wNAF representation is represented by a table of [`Digit`]s which includes one for each
12/// bit of the original scalar, plus an additional bit for any remaining carry, i.e.
13/// `F::NUM_BITS + 1`.
14///
15/// # Examples
16///
17/// See [`WnafBase`] for usage examples.
18#[derive(Clone, Debug, Default)]
19pub struct WnafScalar<F: PrimeField + WnafSize, W: WindowSize> {
20 pub(crate) wnaf: Array<Digit, F::StorageSize>,
21 pub(crate) digits: usize,
22 _field: PhantomData<(F, W)>,
23}
24
25impl<F: PrimeField + WnafSize, W: WindowSize> WnafScalar<F, W> {
26 /// Computes the wNAF representation of the given scalar with window size `W`.
27 #[inline]
28 pub fn new(scalar: &F) -> Self {
29 Self::from_le_bytes(le_repr(scalar).as_ref())
30 }
31
32 /// Computes the wNAF representation directly from raw little-endian bytes.
33 ///
34 /// `bytes` is interpreted as a little-endian unsigned integer (trailing zero bytes may be
35 /// omitted), and the resulting [`WnafScalar`] evaluates to that integer times the base.
36 ///
37 /// Because the number of wNAF digits, and therefore the number of doublings, is proportional
38 /// to `bytes.len() * 8`, passing a slice shorter than the field's canonical representation is
39 /// faster.
40 ///
41 /// # Panics
42 /// If `bytes*8+1 > S::USIZE`.
43 #[inline]
44 #[must_use]
45 pub fn from_le_bytes(bytes: &[u8]) -> Self {
46 let mut wnaf = Self::default();
47 wnaf.init_from_le_bytes(bytes);
48 wnaf
49 }
50
51 /// Initialize wNAF representation directly from raw little-endian bytes, for an already
52 /// allocated [`WnafScalar`].
53 ///
54 /// This is the equivalent of [`WnafScalar::from_le_bytes`] for reusing an existing value.
55 /// See that method for full documentation.
56 ///
57 /// # Panics
58 /// If `bytes` is larger than `F::Repr`.
59 #[inline]
60 pub fn init_from_le_bytes(&mut self, bytes: &[u8]) {
61 debug_assert_eq!(F::NUM_BITS + 1, F::StorageSize::U32);
62 debug_assert!(
63 bytes.len() <= F::NUM_BITS.div_ceil(8) as usize,
64 "input too large: {}",
65 bytes.len(),
66 );
67 let bit_len = (bytes.len() * 8).min(F::NUM_BITS as usize);
68 self.digits = wnaf_form(&mut self.wnaf, bytes, bit_len, W::USIZE);
69 }
70}