use core::{fmt, ops, str};
#[cfg(feature = "serde")]
use serde::ser::SerializeTuple;
use crate::constants;
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Scalar([u8; 32]);
impl_pretty_debug!(Scalar);
impl_non_secure_erase!(Scalar, 0, [0u8; 32]);
const MAX_RAW: [u8; 32] = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40,
];
impl Scalar {
pub const ZERO: Scalar = Scalar(constants::ZERO);
pub const ONE: Scalar = Scalar(constants::ONE);
pub const MAX: Scalar = Scalar(MAX_RAW);
#[cfg(all(feature = "rand", feature = "std"))]
pub fn random() -> Self { Self::random_custom(rand::rng()) }
#[cfg(feature = "rand")]
pub fn random_custom<R: rand::Rng>(mut rng: R) -> Self {
let mut bytes = [0u8; 32];
loop {
rng.fill_bytes(&mut bytes);
if let Ok(scalar) = Scalar::from_be_bytes(bytes) {
break scalar;
}
}
}
pub fn from_be_bytes(value: [u8; 32]) -> Result<Self, OutOfRangeError> {
if value <= MAX_RAW {
Ok(Scalar(value))
} else {
Err(OutOfRangeError {})
}
}
pub fn from_le_bytes(mut value: [u8; 32]) -> Result<Self, OutOfRangeError> {
value.reverse();
Self::from_be_bytes(value)
}
pub fn to_be_bytes(self) -> [u8; 32] { self.0 }
pub fn to_le_bytes(self) -> [u8; 32] {
let mut res = self.0;
res.reverse();
res
}
pub(crate) fn as_be_bytes(&self) -> &[u8; 32] { &self.0 }
pub(crate) fn as_c_ptr(&self) -> *const u8 {
use secp256k1_sys::CPtr;
self.as_be_bytes().as_c_ptr()
}
#[cfg(test)]
#[cfg(all(feature = "rand", feature = "std"))]
pub fn test_random() -> Self { Self::random() }
#[cfg(test)]
#[cfg(not(all(feature = "rand", feature = "std")))]
pub fn test_random() -> Self {
loop {
if let Ok(ret) = Self::from_be_bytes(crate::test_random_32_bytes()) {
return ret;
}
}
}
}
impl<I> ops::Index<I> for Scalar
where
[u8]: ops::Index<I>,
{
type Output = <[u8] as ops::Index<I>>::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output { &self.0[index] }
}
impl From<crate::SecretKey> for Scalar {
fn from(value: crate::SecretKey) -> Self { Scalar(value.to_secret_bytes()) }
}
#[allow(missing_copy_implementations)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[non_exhaustive]
pub struct OutOfRangeError {}
impl fmt::Display for OutOfRangeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt("the value is not a member of secp256k1 field", f)
}
}
#[cfg(feature = "std")]
impl std::error::Error for OutOfRangeError {}
impl str::FromStr for Scalar {
type Err = OutOfRangeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut res = [0u8; 32];
match crate::from_hex(s, &mut res) {
Ok(32) => Scalar::from_be_bytes(res),
_ => Err(OutOfRangeError {}),
}
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Scalar {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
let mut buf = [0u8; 32];
s.serialize_str(
crate::to_hex(&self.to_be_bytes(), &mut buf).expect("fixed-size hex serialization"),
)
} else {
let mut tuple = s.serialize_tuple(32)?;
for byte in self.as_be_bytes().iter() {
tuple.serialize_element(byte)?;
}
tuple.end()
}
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Scalar {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(crate::serde_util::FromStrVisitor::new(
"a hex string representing 32 byte Scalar",
))
} else {
let visitor = crate::serde_util::Tuple32Visitor::new("raw 32 bytes Scalar", |bytes| {
Scalar::from_be_bytes(bytes)
});
d.deserialize_tuple(32, visitor)
}
}
}