From 6d0c7567f056dd894b361ec8166f333fdf748d87 Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Sat, 12 Aug 2023 09:59:02 -0700 Subject: [PATCH] chore: minor code organization improvement --- PQClean | 1 + src/hash/rpo/digest.rs | 126 +++++++++++++++++++++++------------------ 2 files changed, 71 insertions(+), 56 deletions(-) create mode 160000 PQClean diff --git a/PQClean b/PQClean new file mode 160000 index 0000000..c3abebf --- /dev/null +++ b/PQClean @@ -0,0 +1 @@ +Subproject commit c3abebf4ab1ff516ffa71e6337f06d898952c299 diff --git a/src/hash/rpo/digest.rs b/src/hash/rpo/digest.rs index efeda3f..18071ae 100644 --- a/src/hash/rpo/digest.rs +++ b/src/hash/rpo/digest.rs @@ -50,35 +50,54 @@ impl Digest for RpoDigest { } } -impl Serializable for RpoDigest { - fn write_into(&self, target: &mut W) { - target.write_bytes(&self.as_bytes()); +impl Deref for RpoDigest { + type Target = [Felt; DIGEST_SIZE]; + + fn deref(&self) -> &Self::Target { + &self.0 } } -impl Deserializable for RpoDigest { - fn read_from(source: &mut R) -> Result { - let mut inner: [Felt; DIGEST_SIZE] = [ZERO; DIGEST_SIZE]; - for inner in inner.iter_mut() { - let e = source.read_u64()?; - if e >= Felt::MODULUS { - return Err(DeserializationError::InvalidValue(String::from( - "Value not in the appropriate range", - ))); - } - *inner = Felt::new(e); - } +impl Ord for RpoDigest { + fn cmp(&self, other: &Self) -> Ordering { + // compare the inner u64 of both elements. + // + // it will iterate the elements and will return the first computation different than + // `Equal`. Otherwise, the ordering is equal. + // + // the endianness is irrelevant here because since, this being a cryptographically secure + // hash computation, the digest shouldn't have any ordered property of its input. + // + // finally, we use `Felt::inner` instead of `Felt::as_int` so we avoid performing a + // montgomery reduction for every limb. that is safe because every inner element of the + // digest is guaranteed to be in its canonical form (that is, `x in [0,p)`). + self.0.iter().map(Felt::inner).zip(other.0.iter().map(Felt::inner)).fold( + Ordering::Equal, + |ord, (a, b)| match ord { + Ordering::Equal => a.cmp(&b), + _ => ord, + }, + ) + } +} - Ok(Self(inner)) +impl PartialOrd for RpoDigest { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } -impl From<[Felt; DIGEST_SIZE]> for RpoDigest { - fn from(value: [Felt; DIGEST_SIZE]) -> Self { - Self(value) +impl Display for RpoDigest { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let encoded: String = self.into(); + write!(f, "{}", encoded)?; + Ok(()) } } +// CONVERSIONS: FROM RPO DIGEST +// ================================================================================================ + impl From<&RpoDigest> for [Felt; DIGEST_SIZE] { fn from(value: &RpoDigest) -> Self { value.0 @@ -126,17 +145,28 @@ impl From for [u8; DIGEST_BYTES] { } impl From for String { + /// The returned string starts with `0x`. fn from(value: RpoDigest) -> Self { bytes_to_hex_string(value.as_bytes()) } } impl From<&RpoDigest> for String { + /// The returned string starts with `0x`. fn from(value: &RpoDigest) -> Self { (*value).into() } } +// CONVERSIONS: TO DIGEST +// ================================================================================================ + +impl From<[Felt; DIGEST_SIZE]> for RpoDigest { + fn from(value: [Felt; DIGEST_SIZE]) -> Self { + Self(value) + } +} + impl TryFrom<[u8; DIGEST_BYTES]> for RpoDigest { type Error = HexParseError; @@ -159,6 +189,7 @@ impl TryFrom<[u8; DIGEST_BYTES]> for RpoDigest { impl TryFrom<&str> for RpoDigest { type Error = HexParseError; + /// Expects the string to start with `0x`. fn try_from(value: &str) -> Result { hex_to_bytes(value).and_then(|v| v.try_into()) } @@ -167,6 +198,7 @@ impl TryFrom<&str> for RpoDigest { impl TryFrom for RpoDigest { type Error = HexParseError; + /// Expects the string to start with `0x`. fn try_from(value: String) -> Result { value.as_str().try_into() } @@ -175,53 +207,35 @@ impl TryFrom for RpoDigest { impl TryFrom<&String> for RpoDigest { type Error = HexParseError; + /// Expects the string to start with `0x`. fn try_from(value: &String) -> Result { value.as_str().try_into() } } -impl Deref for RpoDigest { - type Target = [Felt; DIGEST_SIZE]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} +// SERIALIZATION / DESERIALIZATION +// ================================================================================================ -impl Ord for RpoDigest { - fn cmp(&self, other: &Self) -> Ordering { - // compare the inner u64 of both elements. - // - // it will iterate the elements and will return the first computation different than - // `Equal`. Otherwise, the ordering is equal. - // - // the endianness is irrelevant here because since, this being a cryptographically secure - // hash computation, the digest shouldn't have any ordered property of its input. - // - // finally, we use `Felt::inner` instead of `Felt::as_int` so we avoid performing a - // montgomery reduction for every limb. that is safe because every inner element of the - // digest is guaranteed to be in its canonical form (that is, `x in [0,p)`). - self.0.iter().map(Felt::inner).zip(other.0.iter().map(Felt::inner)).fold( - Ordering::Equal, - |ord, (a, b)| match ord { - Ordering::Equal => a.cmp(&b), - _ => ord, - }, - ) +impl Serializable for RpoDigest { + fn write_into(&self, target: &mut W) { + target.write_bytes(&self.as_bytes()); } } -impl PartialOrd for RpoDigest { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} +impl Deserializable for RpoDigest { + fn read_from(source: &mut R) -> Result { + let mut inner: [Felt; DIGEST_SIZE] = [ZERO; DIGEST_SIZE]; + for inner in inner.iter_mut() { + let e = source.read_u64()?; + if e >= Felt::MODULUS { + return Err(DeserializationError::InvalidValue(String::from( + "Value not in the appropriate range", + ))); + } + *inner = Felt::new(e); + } -impl Display for RpoDigest { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let encoded: String = self.into(); - write!(f, "{}", encoded)?; - Ok(()) + Ok(Self(inner)) } }