rock_n_rollup/plugins/
hasher.rs

1use blake2::digest::{Update, VariableOutput};
2use blake2::Blake2bVar;
3
4use crate::core::Runtime;
5
6#[derive(PartialEq, Eq, Debug)]
7pub struct Blake2b512([u8; 64]);
8
9#[derive(PartialEq, Eq, Debug)]
10pub struct Blake2b256([u8; 32]);
11
12pub trait Hasher {
13    /// Hash any data to a Blake2b 256 bits
14    fn hash(&mut self, data: &[u8]) -> Blake2b256;
15
16    /// Hash any data to a Blake2b 512 bits
17    fn hash_512(&mut self, data: &[u8]) -> Blake2b512;
18}
19
20impl ToString for Blake2b512 {
21    fn to_string(&self) -> String {
22        self.0
23            .iter()
24            .fold(String::default(), |acc, u8| format!("{}{:02x}", acc, u8))
25    }
26}
27
28impl ToString for Blake2b256 {
29    fn to_string(&self) -> String {
30        self.0
31            .iter()
32            .fold(String::default(), |acc, u8| format!("{}{:02x}", acc, u8))
33    }
34}
35
36impl AsRef<[u8]> for Blake2b512 {
37    fn as_ref(&self) -> &[u8] {
38        &self.0
39    }
40}
41
42impl AsRef<[u8]> for Blake2b256 {
43    fn as_ref(&self) -> &[u8] {
44        &self.0
45    }
46}
47
48impl<R> Hasher for R
49where
50    R: Runtime,
51{
52    fn hash(&mut self, data: &[u8]) -> Blake2b256 {
53        let mut hasher = Blake2bVar::new(32).unwrap();
54        hasher.update(data.as_ref());
55        let mut buf = [0u8; 32];
56        hasher.finalize_variable(&mut buf).unwrap();
57        Blake2b256(buf)
58    }
59
60    fn hash_512(&mut self, data: &[u8]) -> Blake2b512 {
61        let mut hasher = Blake2bVar::new(64).unwrap();
62        hasher.update(data.as_ref());
63        let mut buf = [0u8; 64];
64        hasher.finalize_variable(&mut buf).unwrap();
65        Blake2b512(buf)
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::Hasher;
72    use crate::core::MockRuntime;
73
74    #[test]
75    fn test_hash_512() {
76        let mut runtime = MockRuntime::default();
77        let data = "hello world".as_bytes().to_vec();
78        let hash = runtime.hash_512(&data);
79        let hash = hash.to_string();
80        assert_eq!(hash, "021ced8799296ceca557832ab941a50b4a11f83478cf141f51f933f653ab9fbcc05a037cddbed06e309bf334942c4e58cdf1a46e237911ccd7fcf9787cbc7fd0");
81    }
82
83    #[test]
84    fn equal_hash_256() {
85        let data1: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
86        let data2: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
87        let mut runtime = MockRuntime::default();
88        let hash1 = runtime.hash(&data1);
89        let hash2 = runtime.hash(&data2);
90
91        assert_eq!(hash1, hash2);
92    }
93
94    #[test]
95    fn not_equal_hash_256() {
96        let data1: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
97        let data2: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04, 0x05];
98        let mut runtime = MockRuntime::default();
99        let hash1 = runtime.hash(&data1);
100        let hash2 = runtime.hash(&data2);
101
102        assert_ne!(hash1, hash2);
103    }
104
105    #[test]
106    fn equal_hash_512() {
107        let data1: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
108        let data2: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
109        let mut runtime = MockRuntime::default();
110        let hash1 = runtime.hash_512(&data1);
111        let hash2 = runtime.hash_512(&data2);
112
113        assert_eq!(hash1, hash2);
114    }
115
116    #[test]
117    fn not_equal_hash_512() {
118        let data1: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04];
119        let data2: Vec<u8> = vec![0x01, 0x02, 0x03, 0x04, 0x05];
120        let mut runtime = MockRuntime::default();
121        let hash1 = runtime.hash_512(&data1);
122        let hash2 = runtime.hash_512(&data2);
123
124        assert_ne!(hash1, hash2);
125    }
126}