solana_blake3_hasher/
lib.rs1#![no_std]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7pub use solana_hash::{Hash, ParseHashError, HASH_BYTES, MAX_BASE58_LEN};
8
9#[derive(Clone, Default)]
10#[cfg(all(
11 feature = "blake3",
12 not(any(target_os = "solana", target_arch = "bpf"))
13))]
14pub struct Hasher {
15 hasher: blake3::Hasher,
16}
17
18#[cfg(all(
19 feature = "blake3",
20 not(any(target_os = "solana", target_arch = "bpf"))
21))]
22impl Hasher {
23 pub fn hash(&mut self, val: &[u8]) {
24 self.hasher.update(val);
25 }
26 pub fn hashv(&mut self, vals: &[&[u8]]) {
27 for val in vals {
28 self.hash(val);
29 }
30 }
31 pub fn result(self) -> Hash {
32 Hash::new_from_array(*self.hasher.finalize().as_bytes())
33 }
34}
35
36#[cfg_attr(any(target_os = "solana", target_arch = "bpf"), inline(always))]
38pub fn hashv(vals: &[&[u8]]) -> Hash {
39 #[cfg(not(any(target_os = "solana", target_arch = "bpf")))]
42 {
43 #[cfg(feature = "blake3")]
44 {
45 let mut hasher = Hasher::default();
46 hasher.hashv(vals);
47 hasher.result()
48 }
49 #[cfg(not(feature = "blake3"))]
50 {
51 core::hint::black_box(vals);
52 panic!("hashv is only available on target `solana` or with the `blake3` feature enabled on this crate")
53 }
54 }
55 #[cfg(any(target_os = "solana", target_arch = "bpf"))]
57 {
58 let mut hash_result = core::mem::MaybeUninit::<[u8; solana_hash::HASH_BYTES]>::uninit();
59 unsafe {
61 solana_define_syscall::definitions::sol_blake3(
62 vals as *const _ as *const u8,
63 vals.len() as u64,
64 hash_result.as_mut_ptr() as *mut u8,
65 );
66 Hash::new_from_array(hash_result.assume_init())
67 }
68 }
69}
70
71#[cfg_attr(any(target_os = "solana", target_arch = "bpf"), inline(always))]
73pub fn hash(val: &[u8]) -> Hash {
74 hashv(&[val])
75}
76
77#[cfg(test)]
78#[cfg(feature = "blake3")]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_hashv() {
84 let val = "gHiljKpq";
85 let val_hash = hash(val.as_bytes());
86
87 let ext = "lM890t";
88 let ext_hash = hashv(&[val_hash.as_bytes(), ext.as_bytes()]);
89
90 let hash_ext = [&val_hash.to_bytes(), ext.as_bytes()].concat();
91 assert!(ext_hash == hash(&hash_ext));
92 }
93}