1use crate::trie::{InternalData, LeafData, Node, NodeKind, TERMINATOR};
4
5pub trait NodeHasher {
15 fn hash_leaf(data: &LeafData) -> [u8; 32];
18
19 fn hash_internal(data: &InternalData) -> [u8; 32];
22
23 fn node_kind(node: &Node) -> NodeKind;
25}
26
27pub trait ValueHasher {
29 fn hash_value(value: &[u8]) -> [u8; 32];
31}
32
33pub fn node_kind_by_msb(node: &Node) -> NodeKind {
38 if node[0] >> 7 == 1 {
39 NodeKind::Leaf
40 } else if node == &TERMINATOR {
41 NodeKind::Terminator
42 } else {
43 NodeKind::Internal
44 }
45}
46
47pub fn set_msb(node: &mut Node) {
49 node[0] |= 0b10000000;
50}
51
52pub fn unset_msb(node: &mut Node) {
53 node[0] &= 0b01111111;
54}
55
56pub trait BinaryHash {
58 fn hash(input: &[u8]) -> [u8; 32];
60
61 fn hash2_32_concat(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
63 let mut buf = [0u8; 64];
64 buf[0..32].copy_from_slice(left);
65 buf[32..64].copy_from_slice(right);
66 Self::hash(&buf)
67 }
68}
69
70pub struct BinaryHasher<H>(core::marker::PhantomData<H>);
80
81impl<H: BinaryHash> ValueHasher for BinaryHasher<H> {
82 fn hash_value(value: &[u8]) -> [u8; 32] {
83 H::hash(value)
84 }
85}
86
87impl<H: BinaryHash> NodeHasher for BinaryHasher<H> {
88 fn hash_leaf(data: &LeafData) -> [u8; 32] {
89 let mut h = H::hash2_32_concat(&data.key_path, &data.value_hash);
90 set_msb(&mut h);
91 h
92 }
93
94 fn hash_internal(data: &InternalData) -> [u8; 32] {
95 let mut h = H::hash2_32_concat(&data.left, &data.right);
96 unset_msb(&mut h);
97 h
98 }
99
100 fn node_kind(node: &Node) -> NodeKind {
101 node_kind_by_msb(node)
102 }
103}
104
105impl<H: digest::Digest<OutputSize = digest::typenum::U32> + Send + Sync> BinaryHash for H {
107 fn hash(input: &[u8]) -> [u8; 32] {
108 H::digest(input).into()
109 }
110}
111
112#[cfg(any(feature = "blake3-hasher", test))]
113pub use blake3::Blake3Hasher;
114
115#[cfg(any(feature = "blake3-hasher", test))]
117pub mod blake3 {
118 use super::{BinaryHash, BinaryHasher};
119
120 pub struct Blake3BinaryHasher;
122
123 pub type Blake3Hasher = BinaryHasher<Blake3BinaryHasher>;
125
126 impl BinaryHash for Blake3BinaryHasher {
127 fn hash(value: &[u8]) -> [u8; 32] {
128 blake3::hash(value).into()
129 }
130
131 fn hash2_32_concat(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
132 let mut hasher = blake3::Hasher::new();
133 hasher.update(left);
134 hasher.update(right);
135 hasher.finalize().into()
136 }
137 }
138}
139
140#[cfg(feature = "sha2-hasher")]
141pub use sha2::Sha2Hasher;
142
143#[cfg(feature = "sha2-hasher")]
145pub mod sha2 {
146 use super::{BinaryHash, BinaryHasher};
147 use sha2::{Digest, Sha256};
148
149 pub struct Sha2BinaryHasher;
151
152 pub type Sha2Hasher = BinaryHasher<Sha2BinaryHasher>;
154
155 impl BinaryHash for Sha2BinaryHasher {
156 fn hash(value: &[u8]) -> [u8; 32] {
157 let mut hasher = Sha256::new();
158 hasher.update(value);
159 hasher.finalize().into()
160 }
161
162 fn hash2_32_concat(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
163 let mut hasher = Sha256::new();
164 hasher.update(left);
165 hasher.update(right);
166 hasher.finalize().into()
167 }
168 }
169}