Skip to main content

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}