light_hasher/
keccak.rs

1use crate::{
2    errors::HasherError,
3    zero_bytes::{keccak::ZERO_BYTES, ZeroBytes},
4    zero_indexed_leaf::keccak::ZERO_INDEXED_LEAF,
5    Hash, Hasher,
6};
7
8#[derive(Clone, Copy)] // To allow using with zero copy Solana accounts.
9pub struct Keccak;
10
11impl Hasher for Keccak {
12    const ID: u8 = 2;
13
14    fn hash(val: &[u8]) -> Result<Hash, HasherError> {
15        Self::hashv(&[val])
16    }
17
18    fn hashv(_vals: &[&[u8]]) -> Result<Hash, HasherError> {
19        #[cfg(all(not(target_os = "solana"), feature = "keccak"))]
20        {
21            use sha3::{Digest, Keccak256};
22
23            let mut hasher = Keccak256::default();
24            for val in _vals {
25                hasher.update(val);
26            }
27            Ok(hasher.finalize().into())
28        }
29        #[cfg(all(not(target_os = "solana"), not(feature = "keccak")))]
30        {
31            Err(HasherError::KeccakFeatureNotEnabled)
32        }
33        // Call via a system call to perform the calculation
34        #[cfg(target_os = "solana")]
35        {
36            use crate::HASH_BYTES;
37
38            let mut hash_result = [0; HASH_BYTES];
39            unsafe {
40                crate::syscalls::sol_keccak256(
41                    _vals as *const _ as *const u8,
42                    _vals.len() as u64,
43                    &mut hash_result as *mut _ as *mut u8,
44                );
45            }
46            Ok(hash_result)
47        }
48    }
49
50    fn zero_bytes() -> ZeroBytes {
51        ZERO_BYTES
52    }
53
54    fn zero_indexed_leaf() -> [u8; 32] {
55        ZERO_INDEXED_LEAF
56    }
57}