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 From<[u8; HASH_BYTES]> for Leaf {
31    fn from(from: [u8; 32]) -> Self {
32        Self { 0: Hash { value: from } }
33    }
34}
35
36impl AsRef<[u8]> for Hash {
37    fn as_ref(&self) -> &[u8] {
38        &self.value
39    }
40}
41
42impl AsRef<[u8]> for Leaf {
43    fn as_ref(&self) -> &[u8] {
44        &self.0.value
45    }
46}
47
48impl From<Leaf> for Hash {
49    fn from(leaf: Leaf) -> Self {
50        leaf.0
51    }
52}
53
54impl Hash {
55    pub const LEN: usize = HASH_BYTES;
56
57    pub fn new(hash_slice: &[u8]) -> Self {
58        Hash {
59            value: <[u8; HASH_BYTES]>::try_from(hash_slice).unwrap(),
60        }
61    }
62
63    pub const fn new_from_array(hash_array: [u8; HASH_BYTES]) -> Self {
64        Self { value: hash_array }
65    }
66
67    pub fn to_bytes(self) -> [u8; HASH_BYTES] {
68        self.value
69    }
70
71    pub fn as_leaf(self) -> Leaf {
72        Leaf(self)
73    }
74}
75
76impl Leaf {
77    pub fn new(data: &[&[u8]]) -> Self {
78        let mut inputs = vec![b"LEAF".as_ref()];
79        inputs.extend(data);
80        Leaf(hashv(&inputs))
81    }
82
83    pub fn to_bytes(self) -> [u8; HASH_BYTES] {
84        self.0.value
85    }
86}
87
88#[cfg(feature = "solana")]
89#[inline(always)]
90pub fn hashv(data: &[&[u8]]) -> Hash {
91    let res = solana_program::keccak::hashv(data);
92    Hash::new_from_array(res.to_bytes())
93}
94
95#[cfg(not(feature = "solana"))]
96#[inline(always)]
97pub fn hashv(data: &[&[u8]]) -> Hash {
98    let mut hasher = sha3::Keccak256::new();
99    for d in data {
100        hasher.update(d);
101    }
102    Hash::new_from_array(hasher.finalize().into())
103}
104
105#[cfg(feature = "solana")]
106#[inline(always)]
107pub fn hash(data: &[u8]) -> Hash {
108    let res = solana_program::keccak::hash(data);
109    Hash::new_from_array(res.to_bytes())
110}
111
112#[cfg(not(feature = "solana"))]
113#[inline(always)]
114pub fn hash(data: &[u8]) -> Hash {
115    let mut hasher = sha3::Keccak256::new();
116    hasher.update(data);
117    Hash::new_from_array(hasher.finalize().into())
118}