1use digest::Output;
9
10use crate::{compress::CompressionFunction, suite::HashSuite};
11
12#[derive(Debug, Clone, Default)]
14pub struct Blake3Compression;
15
16impl CompressionFunction<Output<blake3::Hasher>, 2> for Blake3Compression {
17 fn compress(&self, input: [Output<blake3::Hasher>; 2]) -> Output<blake3::Hasher> {
18 let mut hasher = blake3::Hasher::new();
19 hasher.update(input[0].as_slice());
20 hasher.update(input[1].as_slice());
21 (*hasher.finalize().as_bytes()).into()
22 }
23}
24
25#[derive(Debug, Clone, Default)]
27pub struct Blake3HashSuite;
28
29impl HashSuite for Blake3HashSuite {
30 type LeafHash = blake3::Hasher;
31 type Compression = Blake3Compression;
32}
33
34#[cfg(test)]
35mod tests {
36 use rand::{RngExt, SeedableRng, rngs::StdRng};
37
38 use super::*;
39
40 #[test]
41 fn test_compression_matches_reference_hash() {
42 let mut rng = StdRng::seed_from_u64(0);
43 let left: [u8; 32] = rng.random();
44 let right: [u8; 32] = rng.random();
45
46 let compressed = Blake3Compression.compress([left.into(), right.into()]);
47
48 let mut concatenated = [0u8; 64];
50 concatenated[..32].copy_from_slice(&left);
51 concatenated[32..].copy_from_slice(&right);
52 assert_eq!(compressed.as_slice(), blake3::hash(&concatenated).as_bytes());
53 }
54}