uhash_prover/cpu/
solver.rs1use anyhow::Result;
4use uhash_core::{meets_difficulty, UniversalHash};
5
6use crate::solver::{ProofResult, Solver};
7
8pub struct CpuSolver {
11 hasher: UniversalHash,
12}
13
14impl CpuSolver {
15 pub fn new() -> Self {
16 Self {
17 hasher: UniversalHash::new(),
18 }
19 }
20}
21
22impl Default for CpuSolver {
23 fn default() -> Self {
24 Self::new()
25 }
26}
27
28impl Solver for CpuSolver {
29 fn backend_name(&self) -> &'static str {
30 "cpu"
31 }
32
33 fn recommended_lanes(&mut self, requested: usize) -> usize {
34 if requested == 0 {
35 1024
36 } else {
37 requested
38 }
39 }
40
41 fn find_proof_batch(
42 &mut self,
43 header_without_nonce: &[u8],
44 start_nonce: u64,
45 lanes: usize,
46 difficulty: u32,
47 ) -> Result<(ProofResult, usize)> {
48 let mut input = Vec::with_capacity(header_without_nonce.len() + 8);
49 for i in 0..lanes {
50 let nonce = start_nonce.saturating_add(i as u64);
51 input.clear();
52 input.extend_from_slice(header_without_nonce);
53 input.extend_from_slice(&nonce.to_le_bytes());
54 let hash = self.hasher.hash(&input);
55 if meets_difficulty(&hash, difficulty) {
56 return Ok((Some((nonce, hash)), i + 1));
57 }
58 }
59 Ok((None, lanes))
60 }
61
62 fn benchmark_hashes(
63 &mut self,
64 header_without_nonce: &[u8],
65 start_nonce: u64,
66 lanes: usize,
67 ) -> Result<usize> {
68 let mut input = Vec::with_capacity(header_without_nonce.len() + 8);
69 for i in 0..lanes {
70 let nonce = start_nonce.saturating_add(i as u64);
71 input.clear();
72 input.extend_from_slice(header_without_nonce);
73 input.extend_from_slice(&nonce.to_le_bytes());
74 let _ = self.hasher.hash(&input);
75 }
76 Ok(lanes)
77 }
78}