brine_tree/
hash.rs

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