pythnet_sdk/hashers/
prime.rs

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