substrate_runtime_hasher/
lib.rs1use blake2::digest::{Update, VariableOutput};
2use blake2::VarBlake2b;
3use codec::Encode;
4use std::convert::TryInto;
5
6pub const SIZE: usize = 32;
8
9pub type ProposalHash = [u8; SIZE];
11
12const PREFIX: [u8; 2] = [0x00, 0x03];
14
15#[derive(Debug)]
17pub struct SrhResult {
18 pub hash: ProposalHash,
20
21 pub encodedd_hash: String,
23}
24
25pub fn concatenate_arrays<T: Clone>(x: &[T], y: &[T]) -> Vec<T> {
27 let mut concat = x.to_vec();
28 concat.extend_from_slice(y);
29 concat
30}
31
32pub fn get_result(buffer: &[u8]) -> SrhResult {
34 let res = buffer.using_encoded(|ref wasm_blob| {
35 let hash = get_proposal_hash(wasm_blob);
36
37 return SrhResult {
38 hash,
39 encodedd_hash: hex::encode(hash),
40 };
41 });
42 res
43}
44
45fn get_proposal_hash(wasm_blob: &[u8]) -> ProposalHash {
52 let mut hasher = VarBlake2b::new(SIZE).unwrap();
53 hasher.update(concatenate_arrays(&PREFIX, &wasm_blob));
54 let mut result: ProposalHash = [0; SIZE];
55 hasher.finalize_variable(|res| {
56 result = res.try_into().expect("slice with incorrect length");
57 });
58 result
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_hash() {
67 assert_eq!(
68 get_proposal_hash(&[1, 2, 42]),
69 [
70 156, 244, 243, 93, 21, 8, 113, 238, 186, 17, 20, 52, 240, 236, 140, 15, 108, 26,
71 86, 5, 152, 148, 91, 162, 108, 168, 3, 65, 254, 162, 114, 46
72 ]
73 );
74 }
75
76 #[test]
77 fn test_hash_length() {
78 assert_eq!(32, get_proposal_hash(&[0]).len());
79 }
80
81 #[test]
82 fn test_get_result() {
83 let res = get_result(&[1, 2, 42]);
84 assert!(
85 res.encodedd_hash == "9388ba11b3f2a5db3ef9bf237f1c88ffb369d77ffa843fc67570c89c09fa9c0e"
86 );
87 }
88
89 #[test]
90 fn test_long_input() {
91 const SIZE_8MB: usize = 8 * 1024 * 1024;
92 let res = get_result(&[0; SIZE_8MB]);
93 assert!(
94 res.encodedd_hash == "9348da94fcffe94318313f8ce237211a7fd6c1531ab21b61606a1f7eeb8b2409"
95 );
96 }
97}