1use core::{fmt, ops};
12
13use crate::constants;
14
15#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
26pub struct Scalar([u8; 32]);
27impl_pretty_debug!(Scalar);
28impl_non_secure_erase!(Scalar, 0, [0u8; 32]);
29
30const MAX_RAW: [u8; 32] = [
31 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
32 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40,
33];
34
35impl Scalar {
36 pub const ZERO: Scalar = Scalar(constants::ZERO);
38 pub const ONE: Scalar = Scalar(constants::ONE);
40 pub const MAX: Scalar = Scalar(MAX_RAW);
42
43 #[cfg(all(feature = "rand", feature = "std"))]
45 pub fn random() -> Self { Self::random_custom(rand::rng()) }
46
47 #[cfg(feature = "rand")]
49 pub fn random_custom<R: rand::Rng>(mut rng: R) -> Self {
50 let mut bytes = [0u8; 32];
51 loop {
52 rng.fill_bytes(&mut bytes);
53 if let Ok(scalar) = Scalar::from_be_bytes(bytes) {
55 break scalar;
56 }
57 }
58 }
59
60 pub fn from_be_bytes(value: [u8; 32]) -> Result<Self, OutOfRangeError> {
69 if value <= MAX_RAW {
71 Ok(Scalar(value))
72 } else {
73 Err(OutOfRangeError {})
74 }
75 }
76
77 pub fn from_le_bytes(mut value: [u8; 32]) -> Result<Self, OutOfRangeError> {
86 value.reverse();
87 Self::from_be_bytes(value)
88 }
89
90 pub fn to_be_bytes(self) -> [u8; 32] { self.0 }
92
93 pub fn to_le_bytes(self) -> [u8; 32] {
95 let mut res = self.0;
96 res.reverse();
97 res
98 }
99
100 pub(crate) fn as_be_bytes(&self) -> &[u8; 32] { &self.0 }
103
104 pub(crate) fn as_c_ptr(&self) -> *const u8 {
105 use secp256k1_sys::CPtr;
106
107 self.as_be_bytes().as_c_ptr()
108 }
109
110 #[cfg(test)]
112 #[cfg(all(feature = "rand", feature = "std"))]
113 pub fn test_random() -> Self { Self::random() }
114
115 #[cfg(test)]
117 #[cfg(not(all(feature = "rand", feature = "std")))]
118 pub fn test_random() -> Self {
119 loop {
120 if let Ok(ret) = Self::from_be_bytes(crate::test_random_32_bytes()) {
121 return ret;
122 }
123 }
124 }
125}
126
127impl<I> ops::Index<I> for Scalar
128where
129 [u8]: ops::Index<I>,
130{
131 type Output = <[u8] as ops::Index<I>>::Output;
132
133 #[inline]
134 fn index(&self, index: I) -> &Self::Output { &self.0[index] }
135}
136
137impl From<crate::SecretKey> for Scalar {
138 fn from(value: crate::SecretKey) -> Self { Scalar(value.to_secret_bytes()) }
139}
140
141#[allow(missing_copy_implementations)]
145#[derive(Debug, Clone, Eq, PartialEq, Hash)]
146#[non_exhaustive]
147pub struct OutOfRangeError {}
148
149impl fmt::Display for OutOfRangeError {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 fmt::Display::fmt("the value is not a member of secp256k1 field", f)
152 }
153}
154
155#[cfg(feature = "std")]
156impl std::error::Error for OutOfRangeError {}