pythnet_sdk/hashers/
prime.rs

1use {
2    crate::hashers::Hasher,
3    serde::Serialize,
4    sha3::Digest,
5    slow_primes::is_prime_miller_rabin,
6};
7
8#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize)]
9pub struct PrimeHasher {}
10
11impl Hasher for PrimeHasher {
12    // u128 in big endian bytes
13    type Hash = [u8; 16];
14
15    fn hashv(data: &[impl AsRef<[u8]>]) -> [u8; 16] {
16        // Scan for primes generated by hashing the bytes starting from 0. We use a number like
17        // this so once the prime is found we can directly compute the hash instead of scanning
18        // the range again.
19        let mut search = 0usize;
20
21        loop {
22            // Increment Search Counter.
23            search += 1;
24
25            // Hash Input.
26            let mut hasher = sha3::Sha3_256::new();
27            for d in data {
28                hasher.update(d);
29            }
30            hasher.update(search.to_be_bytes());
31            let hash_bytes: [u8; 32] = hasher.finalize().into();
32
33            // Take only a u32 from the end, return if its prime.
34            let prime = u32::from_be_bytes(hash_bytes[28..].try_into().unwrap()) | 1;
35            if is_prime_miller_rabin(prime as u64) {
36                return (prime as u128).to_be_bytes();
37            }
38        }
39    }
40}