arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/crypto/src/hash/rpo/digest.rs
crypto/src/hash/rpo/digest.rsRaw
  1use super::DIGEST_SIZE;
  2use crate::{Digest, Felt, StarkField};
  3use core::slice;
  4use winterfell::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
  5
  6// DIGEST TRAIT IMPLEMENTATIONS
  7// ================================================================================================
  8
  9#[derive(Debug, Copy, Clone, Eq, PartialEq)]
 10pub struct RpoDigest256([Felt; DIGEST_SIZE]);
 11
 12impl RpoDigest256 {
 13    pub fn new(value: [Felt; DIGEST_SIZE]) -> Self {
 14        Self(value)
 15    }
 16
 17    pub fn as_elements(&self) -> &[Felt] {
 18        &self.0
 19    }
 20
 21    pub fn digests_as_elements(digests: &[Self]) -> &[Felt] {
 22        let p = digests.as_ptr();
 23        let len = digests.len() * DIGEST_SIZE;
 24        unsafe { slice::from_raw_parts(p as *const Felt, len) }
 25    }
 26}
 27
 28impl Digest for RpoDigest256 {
 29    fn as_bytes(&self) -> [u8; 32] {
 30        let mut result = [0; 32];
 31
 32        result[..8].copy_from_slice(&self.0[0].as_int().to_le_bytes());
 33        result[8..16].copy_from_slice(&self.0[1].as_int().to_le_bytes());
 34        result[16..24].copy_from_slice(&self.0[2].as_int().to_le_bytes());
 35        result[24..].copy_from_slice(&self.0[3].as_int().to_le_bytes());
 36
 37        result
 38    }
 39}
 40
 41impl Default for RpoDigest256 {
 42    fn default() -> Self {
 43        RpoDigest256([Felt::default(); DIGEST_SIZE])
 44    }
 45}
 46
 47impl Serializable for RpoDigest256 {
 48    fn write_into<W: ByteWriter>(&self, target: &mut W) {
 49        target.write_u8_slice(&self.as_bytes());
 50    }
 51}
 52
 53impl Deserializable for RpoDigest256 {
 54    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
 55        // TODO: check if the field elements are valid?
 56        let e1 = Felt::new(source.read_u64()?);
 57        let e2 = Felt::new(source.read_u64()?);
 58        let e3 = Felt::new(source.read_u64()?);
 59        let e4 = Felt::new(source.read_u64()?);
 60
 61        Ok(Self([e1, e2, e3, e4]))
 62    }
 63}
 64
 65impl From<[Felt; DIGEST_SIZE]> for RpoDigest256 {
 66    fn from(value: [Felt; DIGEST_SIZE]) -> Self {
 67        Self(value)
 68    }
 69}
 70
 71impl From<RpoDigest256> for [Felt; DIGEST_SIZE] {
 72    fn from(value: RpoDigest256) -> Self {
 73        value.0
 74    }
 75}
 76
 77impl From<RpoDigest256> for [u8; 32] {
 78    fn from(value: RpoDigest256) -> Self {
 79        value.as_bytes()
 80    }
 81}
 82
 83// TESTS
 84// ================================================================================================
 85
 86#[cfg(test)]
 87mod tests {
 88
 89    use super::RpoDigest256;
 90    use crate::Felt;
 91    use rand_utils::rand_value;
 92    use winterfell::{Deserializable, Serializable, SliceReader};
 93
 94    #[test]
 95    fn digest_serialization() {
 96        let e1 = Felt::new(rand_value());
 97        let e2 = Felt::new(rand_value());
 98        let e3 = Felt::new(rand_value());
 99        let e4 = Felt::new(rand_value());
100
101        let d1 = RpoDigest256([e1, e2, e3, e4]);
102
103        let mut bytes = vec![];
104        d1.write_into(&mut bytes);
105        assert_eq!(32, bytes.len());
106
107        let mut reader = SliceReader::new(&bytes);
108        let d2 = RpoDigest256::read_from(&mut reader).unwrap();
109
110        assert_eq!(d1, d2);
111    }
112}