1use serde::{Deserialize, Serialize};
2use sha2::{Digest, Sha256};
3use solana_sdk::bs58;
4use std::{convert::TryFrom, fmt};
5
6pub const HASH_BYTES: usize = 32;
7
8#[derive(Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
9#[repr(transparent)]
10pub struct Hash(pub [u8; HASH_BYTES]);
11
12#[derive(Clone, Default)]
13pub struct Hasher {
14 hasher: Sha256,
15}
16
17impl Hasher {
18 pub fn hash(&mut self, val: &[u8]) {
19 self.hasher.update(val);
20 }
21 pub fn hashv(&mut self, vals: &[&[u8]]) {
22 for val in vals {
23 self.hash(val);
24 }
25 }
26 pub fn result(self) -> Hash {
27 Hash(<[u8; HASH_BYTES]>::try_from(self.hasher.finalize().as_slice()).unwrap())
30 }
31}
32
33impl AsRef<[u8]> for Hash {
34 fn as_ref(&self) -> &[u8] {
35 &self.0[..]
36 }
37}
38
39impl fmt::Debug for Hash {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 write!(f, "{}", bs58::encode(self.0).into_string())
42 }
43}
44
45impl fmt::Display for Hash {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 write!(f, "{}", bs58::encode(self.0).into_string())
48 }
49}
50
51impl Hash {
52 pub fn new(hash_slice: &[u8]) -> Self {
53 Hash(<[u8; HASH_BYTES]>::try_from(hash_slice).unwrap())
54 }
55
56 pub fn to_bytes(self) -> [u8; HASH_BYTES] {
57 self.0
58 }
59}
60
61pub fn hashv(vals: &[&[u8]]) -> Hash {
63 #[cfg(not(target_arch = "bpf"))]
66 {
67 let mut hasher = Hasher::default();
68 hasher.hashv(vals);
69 hasher.result()
70 }
71}
72
73pub fn hash(val: &[u8]) -> Hash {
75 hashv(&[val])
76}
77
78pub fn sighash(namespace: &str, name: &str) -> [u8; 8] {
79 let preimage = format!("{}:{}", namespace, name);
80
81 let mut sighash = [0u8; 8];
82 sighash.copy_from_slice(&hash(preimage.as_bytes()).to_bytes()[..8]);
83 sighash
84}