starknet_rust_crypto/
blake2s_hash.rs1use blake2::Blake2s256;
2use digest::Digest;
3use starknet_types_core::{felt::Felt, hash::Blake2Felt252};
4
5#[derive(Debug, Default, Clone)]
9pub struct Blake2Hasher {
10 hasher: Blake2s256,
11}
12
13impl Blake2Hasher {
14 pub fn new() -> Self {
16 Self::default()
17 }
18
19 pub fn update(&mut self, msg: Felt) {
21 let u32_words = Blake2Felt252::encode_felts_to_u32s(&[msg]);
23
24 let mut buf = [0u8; 8 * 4]; let mut offset = 0;
28
29 for word in u32_words {
30 let bytes = word.to_le_bytes();
31 buf[offset..offset + 4].copy_from_slice(&bytes);
32 offset += 4;
33 }
34
35 self.hasher.update(&buf[0..offset]);
36 }
37
38 pub fn finalize(self) -> Felt {
40 let hash32 = self.hasher.finalize();
41 pack_256_le_to_felt(hash32.as_slice())
42 }
43}
44
45#[inline(always)]
47pub fn blake2s_hash(x: Felt, y: Felt) -> Felt {
48 Blake2Felt252::encode_felt252_data_and_calc_blake_hash(&[x, y])
50}
51
52#[inline(always)]
54pub fn blake2s_hash_single(x: Felt) -> Felt {
55 Blake2Felt252::encode_felt252_data_and_calc_blake_hash(&[x])
57}
58
59#[inline(always)]
63pub fn blake2s_hash_many(msgs: &[Felt]) -> Felt {
64 Blake2Felt252::encode_felt252_data_and_calc_blake_hash(msgs)
65}
66
67fn pack_256_le_to_felt(bytes: &[u8]) -> Felt {
70 assert!(bytes.len() >= 32, "need at least 32 bytes to pack 8 words");
71
72 let mut buf = [0u8; 32];
74 buf[..32].copy_from_slice(&bytes[..32]);
75
76 Felt::from_bytes_le(&buf)
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use test_case::test_case;
84
85 #[test_case(vec![] => "874258848688468311465623299960361657518391155660316941922502367727700287818"; "empty_input")]
87 #[test_case(vec![Felt::from((1u64 << 63) - 1)] => "94160078030592802631039216199460125121854007413180444742120780261703604445"; "max_i64")]
88 #[test_case(vec![Felt::from(1u64 << 63)] => "318549634615606806810268830802792194529205864650702991817600345489579978482"; "i64_sign_boundary")]
89 #[test_case(vec![Felt::from_hex_unchecked("800000000000011000000000000000000000000000000000000000000000000")] => "3505594194634492896230805823524239179921427575619914728883524629460058657521"; "large_hex")]
90 #[test_case(vec![Felt::from(42), Felt::from(1u64 << 63), Felt::from(1337)] => "1127477916086913892828040583976438888091205536601278656613505514972451246501"; "mixed_sizes")]
91 #[test_case(vec![Felt::from(u64::MAX)] => "3515074221976790747383295076946184515593027667350620348239642126105984996390"; "u64_max")]
92 fn test_encode_felt252_data_and_calc_blake_hash(input: Vec<Felt>) -> String {
93 let result_hash_many = blake2s_hash_many(&input);
94
95 let mut hasher = Blake2Hasher::new();
97 for &felt in &input {
98 hasher.update(felt);
99 }
100 let result_blake = hasher.finalize();
101
102 assert_eq!(result_hash_many, result_blake);
103
104 result_hash_many.to_string()
106 }
107}