1use super::PowStrategy;
2use crate::PoWSolution;
3
4#[derive(Clone, Copy)]
5pub struct KeccakPoW {
6 challenge: [u64; 4],
7 threshold: u64,
8 state: [u64; 25],
9}
10
11impl PowStrategy for KeccakPoW {
12 #[allow(clippy::cast_sign_loss)]
13 fn new(challenge: [u8; 32], bits: f64) -> Self {
14 let threshold = (64.0 - bits).exp2().ceil() as u64;
15 Self {
16 challenge: bytemuck::cast(challenge),
17 threshold,
18 state: [0; 25],
19 }
20 }
21
22 fn solution(&self, nonce: u64) -> PoWSolution {
23 PoWSolution {
24 challenge: bytemuck::cast(self.challenge),
25 nonce,
26 }
27 }
28
29 fn check(&mut self, nonce: u64) -> bool {
30 self.state[..4].copy_from_slice(&self.challenge);
31 self.state[4] = nonce;
32 for s in self.state.iter_mut().skip(5) {
33 *s = 0;
34 }
35 keccak::f1600(&mut self.state);
36 self.state[0] < self.threshold
37 }
38}
39
40#[test]
41fn test_pow_keccak() {
42 use crate::{convenience::*, PoWGrinder};
43
44 const BITS: f64 = 10.0;
45
46 let challenge = [42u8; 32];
48
49 let _solution = grind_pow::<KeccakPoW>(challenge, BITS).expect("Should find a valid solution");
51
52 let mut grounder = PoWGrinder::<KeccakPoW>::new(challenge, BITS);
55 let _solution2 = grounder.grind().expect("Should find a valid solution");
56
57 assert!(grind_pow::<KeccakPoW>(challenge, BITS).is_some());
60}