crm_cli_utils/
sighash.rs

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        // At the time of this writing, the sha2 library is stuck on an old version
28        // of generic_array (0.9.0). Decouple ourselves with a clone to our version.
29        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
61/// Return a Sha256 hash for the given data.
62pub fn hashv(vals: &[&[u8]]) -> Hash {
63    // Perform the calculation inline, calling this from within a program is
64    // not supported
65    #[cfg(not(target_arch = "bpf"))]
66    {
67        let mut hasher = Hasher::default();
68        hasher.hashv(vals);
69        hasher.result()
70    }
71}
72
73/// Return a Sha256 hash for the given data.
74pub 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}