1use crate::check::Check;
9use crate::error::{Error, Result};
10use crate::io::{Reader, Writer};
11use sha2::{Digest, Sha256};
12
13pub const LHAS_HEADER_LEN: usize = 38;
15pub const HASH_ALGORITHM_SHA256: u8 = 0x01;
17pub const HASH_SIZE_SHA256: u8 = 32;
19
20#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct LayerHashes {
23 pub hash_algorithm: u8,
25 pub hash_size: u8,
27 pub layer_count: u32,
29 pub merkle_root: [u8; 32],
31 pub layer_hashes: Vec<[u8; 32]>,
33}
34
35impl LayerHashes {
36 pub fn parse(payload: &[u8]) -> Result<LayerHashes> {
38 let mut r = Reader::checked(payload, Check::LhasFrame);
39 let hash_algorithm = r.u8()?;
40 let hash_size = r.u8()?;
41 let layer_count = r.u32()?;
42 let merkle_root = r.array::<32>()?;
43 if hash_algorithm != HASH_ALGORITHM_SHA256 || hash_size != HASH_SIZE_SHA256 {
44 return Err(Error::new(
45 Check::LhasHashAlgorithm,
46 format!(
47 "hash_algorithm {hash_algorithm:#04x} with hash_size {hash_size} is not SHA-256"
48 ),
49 ));
50 }
51 let table_len = (layer_count as usize)
52 .checked_mul(HASH_SIZE_SHA256 as usize)
53 .ok_or_else(|| Error::new(Check::LhasFrame, "the leaf table length overflows"))?;
54 if table_len > r.remaining() {
55 return Err(Error::new(
56 Check::LhasFrame,
57 format!(
58 "{layer_count} leaf hashes need {table_len} bytes, {} remain",
59 r.remaining()
60 ),
61 ));
62 }
63 let mut layer_hashes = Vec::with_capacity(layer_count as usize);
64 for _ in 0..layer_count {
65 layer_hashes.push(r.array::<32>()?);
66 }
67 Ok(LayerHashes {
68 hash_algorithm,
69 hash_size,
70 layer_count,
71 merkle_root,
72 layer_hashes,
73 })
74 }
75
76 pub fn to_bytes(&self) -> Vec<u8> {
78 let mut w = Writer::with_capacity(LHAS_HEADER_LEN + self.layer_hashes.len() * 32);
79 w.u8(self.hash_algorithm);
80 w.u8(self.hash_size);
81 w.u32(self.layer_count);
82 w.bytes(&self.merkle_root);
83 for leaf in &self.layer_hashes {
84 w.bytes(leaf);
85 }
86 w.into_vec()
87 }
88}
89
90pub fn leaf_hash(data: &[u8]) -> [u8; 32] {
94 let mut hasher = Sha256::new();
95 hasher.update([0x00u8]);
96 hasher.update(data);
97 hasher.finalize().into()
98}
99
100fn internal_hash(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
102 let mut hasher = Sha256::new();
103 hasher.update([0x01u8]);
104 hasher.update(left);
105 hasher.update(right);
106 hasher.finalize().into()
107}
108
109fn empty_internal_hash() -> [u8; 32] {
115 let mut hasher = Sha256::new();
116 hasher.update([0x01u8]);
117 hasher.finalize().into()
118}
119
120pub fn merkle_root(leaves: &[[u8; 32]]) -> [u8; 32] {
122 if leaves.is_empty() {
123 return empty_internal_hash();
124 }
125 let mut level = leaves.to_vec();
126 while level.len() > 1 {
127 let mut next = Vec::with_capacity(level.len().div_ceil(2));
128 let mut i = 0;
129 while i + 1 < level.len() {
130 next.push(internal_hash(&level[i], &level[i + 1]));
131 i += 2;
132 }
133 if i < level.len() {
134 next.push(level[i]);
136 }
137 level = next;
138 }
139 level.into_iter().next().unwrap_or_else(empty_internal_hash)
140}
141
142fn sibling_flags(mut n: usize, mut index: usize) -> Vec<bool> {
145 let mut flags = Vec::new();
146 while n > 1 {
147 flags.push(index % 2 == 1 || index + 1 < n);
148 index >>= 1;
149 n = n.div_ceil(2);
150 }
151 flags
152}
153
154fn sibling_count(mut n: usize, mut index: usize) -> usize {
156 let mut count = 0;
157 while n > 1 {
158 if index % 2 == 1 || index + 1 < n {
159 count += 1;
160 }
161 index >>= 1;
162 n = n.div_ceil(2);
163 }
164 count
165}
166
167fn fold_flags(
169 leaf: &[u8; 32],
170 path: &[[u8; 32]],
171 mut index: usize,
172 flags: &[bool],
173) -> Option<[u8; 32]> {
174 let mut acc = *leaf;
175 let mut used = 0;
176 for &has_sibling in flags {
177 if has_sibling {
178 let sibling = path.get(used)?;
179 acc = if index & 1 == 1 {
180 internal_hash(sibling, &acc)
181 } else {
182 internal_hash(&acc, sibling)
183 };
184 used += 1;
185 }
186 index >>= 1;
187 }
188 Some(acc)
189}
190
191pub fn merkle_path(leaves: &[[u8; 32]], index: usize) -> Vec<[u8; 32]> {
196 let mut path = Vec::new();
197 if index >= leaves.len() {
198 return path;
199 }
200 let mut level = leaves.to_vec();
201 let mut i = index;
202 while level.len() > 1 {
203 if i % 2 == 1 {
204 if let Some(left) = level.get(i - 1) {
205 path.push(*left);
206 }
207 } else if let Some(right) = level.get(i + 1) {
208 path.push(*right);
209 }
210 let mut next = Vec::with_capacity(level.len().div_ceil(2));
211 let mut k = 0;
212 while k + 1 < level.len() {
213 next.push(internal_hash(&level[k], &level[k + 1]));
214 k += 2;
215 }
216 if k < level.len() {
217 next.push(level[k]);
218 }
219 level = next;
220 i >>= 1;
221 }
222 path
223}
224
225pub fn verify_leaf(leaf: &[u8; 32], path: &[[u8; 32]], index: usize, root: &[u8; 32]) -> bool {
227 let mut acc = *leaf;
230 let mut i = index;
231 for sibling in path {
232 acc = if i & 1 == 1 {
233 internal_hash(sibling, &acc)
234 } else {
235 internal_hash(&acc, sibling)
236 };
237 i >>= 1;
238 }
239 if &acc == root {
240 return true;
241 }
242
243 let target = path.len();
248 let mut lo = index.saturating_add(1);
249 let mut hi = index.saturating_mul(2).saturating_add(2);
250 if sibling_count(lo, index) > target {
251 return false;
252 }
253 while lo < hi {
254 let mid = lo + (hi - lo) / 2;
255 if sibling_count(mid, index) < target {
256 lo = mid + 1;
257 } else {
258 hi = mid;
259 }
260 }
261 if sibling_count(lo, index) != target {
262 return false;
263 }
264 fold_flags(leaf, path, index, &sibling_flags(lo, index)) == Some(*root)
265}
266
267#[cfg(test)]
268mod tests {
269 use super::*;
270
271 fn sha(parts: &[&[u8]]) -> [u8; 32] {
274 let mut hasher = Sha256::new();
275 for part in parts {
276 hasher.update(part);
277 }
278 hasher.finalize().into()
279 }
280
281 fn leaves(n: usize) -> Vec<[u8; 32]> {
282 (0..n).map(|i| leaf_hash(&[i as u8; 4])).collect()
283 }
284
285 #[test]
286 fn leaf_hash_prefixes_the_data_with_zero() {
287 assert_eq!(leaf_hash(b"abc"), sha(&[&[0x00], b"abc"]));
288 assert_eq!(leaf_hash(b""), sha(&[&[0x00]]));
289 assert_ne!(leaf_hash(b"abc"), sha(&[b"abc"]));
290 }
291
292 #[test]
293 fn merkle_root_handles_one_two_three_and_five_leaves() {
294 let l = leaves(5);
295 let node = |left: &[u8; 32], right: &[u8; 32]| sha(&[&[0x01], left, right]);
296
297 assert_eq!(merkle_root(&l[..1]), l[0]);
298 assert_eq!(merkle_root(&l[..2]), node(&l[0], &l[1]));
299
300 let promoted = node(&l[0], &l[1]);
302 assert_eq!(merkle_root(&l[..3]), node(&promoted, &l[2]));
303 let duplicated = node(&promoted, &node(&l[2], &l[2]));
304 assert_ne!(merkle_root(&l[..3]), duplicated);
305
306 let top = node(&node(&l[0], &l[1]), &node(&l[2], &l[3]));
308 assert_eq!(merkle_root(&l[..5]), node(&top, &l[4]));
309 }
310
311 #[test]
312 fn merkle_path_verifies_every_leaf_including_promoted_ones() {
313 let l = leaves(5);
314 let root = merkle_root(&l);
315 for (i, leaf) in l.iter().enumerate() {
316 let path = merkle_path(&l, i);
317 assert!(verify_leaf(leaf, &path, i, &root), "leaf {i} should verify");
318 let mut flipped = *leaf;
319 flipped[0] ^= 0x01;
320 assert!(
321 !verify_leaf(&flipped, &path, i, &root),
322 "flipped leaf {i} must not verify"
323 );
324 }
325
326 let l3 = leaves(3);
328 let root3 = merkle_root(&l3);
329 let path = merkle_path(&l3, 2);
330 assert!(verify_leaf(&l3[2], &path, 2, &root3));
331 assert!(merkle_path(&l3, 3).is_empty());
332 }
333
334 #[test]
335 fn lhas_round_trips_and_rejects_bad_payloads() {
336 let hashes = LayerHashes {
337 hash_algorithm: HASH_ALGORITHM_SHA256,
338 hash_size: HASH_SIZE_SHA256,
339 layer_count: 3,
340 merkle_root: [7u8; 32],
341 layer_hashes: vec![[1u8; 32], [2u8; 32], [3u8; 32]],
342 };
343 let bytes = hashes.to_bytes();
344 assert_eq!(bytes.len(), LHAS_HEADER_LEN + 3 * 32);
345 assert_eq!(LayerHashes::parse(&bytes).unwrap(), hashes);
346
347 assert_eq!(
348 LayerHashes::parse(&bytes[..LHAS_HEADER_LEN - 1])
349 .unwrap_err()
350 .check(),
351 Check::LhasFrame
352 );
353
354 let mut wrong_algorithm = bytes.clone();
355 wrong_algorithm[0] = 2;
356 assert_eq!(
357 LayerHashes::parse(&wrong_algorithm).unwrap_err().check(),
358 Check::LhasHashAlgorithm
359 );
360
361 let mut short = bytes.clone();
362 short[2..6].copy_from_slice(&9u32.to_le_bytes());
363 assert_eq!(
364 LayerHashes::parse(&short).unwrap_err().check(),
365 Check::LhasFrame
366 );
367 }
368}