brine_tree/
hash.rs

1use bytemuck::{Pod, Zeroable};
2
3pub const HASH_BYTES: usize = 32;
4
5#[repr(C)]
6#[derive(Clone, Copy, PartialEq, Debug, Default, Pod, Zeroable)]
7pub struct Hash {
8    pub(crate) value: [u8; 32],
9}
10
11#[repr(C)]
12#[derive(Clone, Copy, PartialEq, Debug, Pod, Zeroable)]
13pub struct Leaf(Hash);
14
15impl From<Hash> for [u8; HASH_BYTES] {
16    fn from(from: Hash) -> Self {
17        from.value
18    }
19}
20
21impl From<[u8; HASH_BYTES]> for Hash {
22    fn from(from: [u8; 32]) -> Self {
23        Self { value: from }
24    }
25}
26
27impl From<[u8; HASH_BYTES]> for Leaf {
28    fn from(from: [u8; 32]) -> Self {
29        Self(Hash { value: from })
30    }
31}
32
33impl AsRef<[u8]> for Hash {
34    fn as_ref(&self) -> &[u8] {
35        &self.value
36    }
37}
38
39impl AsRef<[u8]> for Leaf {
40    fn as_ref(&self) -> &[u8] {
41        &self.0.value
42    }
43}
44
45impl From<Leaf> for Hash {
46    fn from(leaf: Leaf) -> Self {
47        leaf.0
48    }
49}
50
51impl Hash {
52    pub const LEN: usize = HASH_BYTES;
53
54    pub fn new(hash_slice: &[u8]) -> Self {
55        Hash {
56            value: <[u8; HASH_BYTES]>::try_from(hash_slice).unwrap(),
57        }
58    }
59
60    pub const fn new_from_array(hash_array: [u8; HASH_BYTES]) -> Self {
61        Self { value: hash_array }
62    }
63
64    pub fn to_bytes(self) -> [u8; HASH_BYTES] {
65        self.value
66    }
67
68    pub fn as_leaf(self) -> Leaf {
69        Leaf(self)
70    }
71}
72
73impl Leaf {
74    pub fn new(data: &[&[u8]]) -> Self {
75        let mut inputs = vec![b"LEAF".as_ref()];
76        inputs.extend(data);
77        Leaf(hashv(&inputs))
78    }
79
80    pub fn to_bytes(self) -> [u8; HASH_BYTES] {
81        self.0.value
82    }
83}
84
85#[cfg(feature = "solana")]
86#[inline(always)]
87pub fn hashv(data: &[&[u8]]) -> Hash {
88    let res = solana_program::blake3::hashv(data);
89    Hash::new_from_array(res.to_bytes())
90}
91
92#[cfg(not(feature = "solana"))]
93#[inline(always)]
94pub fn hashv(data: &[&[u8]]) -> Hash {
95    let mut hasher = blake3::Hasher::new();
96    for d in data {
97        hasher.update(d);
98    }
99    Hash::new_from_array(hasher.finalize().into())
100}
101
102#[cfg(feature = "solana")]
103#[inline(always)]
104pub fn hash(data: &[u8]) -> Hash {
105    let res = solana_program::blake3::hash(data);
106    Hash::new_from_array(res.to_bytes())
107}
108
109#[cfg(not(feature = "solana"))]
110#[inline(always)]
111pub fn hash(data: &[u8]) -> Hash {
112    let mut hasher = blake3::Hasher::new();
113    hasher.update(data);
114    Hash::new_from_array(hasher.finalize().into())
115}