uhash-prover 0.4.1

UniversalHash solver backends (CPU/GPU) without chain transport
Documentation
//! Single-threaded CPU solver.

use anyhow::Result;
use uhash_core::{meets_difficulty, UniversalHash};

use crate::solver::{ProofResult, Solver};

/// Single-threaded CPU solver. Reuses one `UniversalHash` instance to
/// avoid repeated 2 MB scratchpad allocations.
pub struct CpuSolver {
    hasher: UniversalHash,
}

impl CpuSolver {
    pub fn new() -> Self {
        Self {
            hasher: UniversalHash::new(),
        }
    }
}

impl Default for CpuSolver {
    fn default() -> Self {
        Self::new()
    }
}

impl Solver for CpuSolver {
    fn backend_name(&self) -> &'static str {
        "cpu"
    }

    fn recommended_lanes(&mut self, requested: usize) -> usize {
        if requested == 0 {
            1024
        } else {
            requested
        }
    }

    fn find_proof_batch(
        &mut self,
        header_without_nonce: &[u8],
        start_nonce: u64,
        lanes: usize,
        difficulty: u32,
    ) -> Result<ProofResult> {
        let mut input = Vec::with_capacity(header_without_nonce.len() + 8);
        for i in 0..lanes {
            let nonce = start_nonce.saturating_add(i as u64);
            input.clear();
            input.extend_from_slice(header_without_nonce);
            input.extend_from_slice(&nonce.to_le_bytes());
            let hash = self.hasher.hash(&input);
            if meets_difficulty(&hash, difficulty) {
                return Ok(Some((nonce, hash)));
            }
        }
        Ok(None)
    }

    fn benchmark_hashes(
        &mut self,
        header_without_nonce: &[u8],
        start_nonce: u64,
        lanes: usize,
    ) -> Result<usize> {
        let mut input = Vec::with_capacity(header_without_nonce.len() + 8);
        for i in 0..lanes {
            let nonce = start_nonce.saturating_add(i as u64);
            input.clear();
            input.extend_from_slice(header_without_nonce);
            input.extend_from_slice(&nonce.to_le_bytes());
            let _ = self.hasher.hash(&input);
        }
        Ok(lanes)
    }
}