Skip to main content

hashiverse_lib/tools/pow_generator/
single_threaded_pow_generator.rs

1//! Single-threaded PoW search that works on every target.
2//!
3//! No `spawn_blocking`, no Web Workers — `run_chunk` just runs the PoW measurement loop
4//! inline. WASM clients use this directly (with a relaxed `pow_min`) before workers are
5//! wired up; native callers can use it in unit tests where setting up a thread pool would
6//! be overkill.
7//!
8//! Despite the simplicity, this generator does real PoW work — it is not a no-op stub.
9//! All the orchestration (work-stealing, early-exit, tracker registration) lives in the
10//! shared [`crate::tools::pow_generator::pow_generator::run_pool`] dispatcher.
11
12use crate::tools::pow_generator::pow_generator;
13use crate::tools::pow_generator::pow_generator::{JobTracker, PowGenerator};
14use crate::tools::types::{Hash, Pow, Salt};
15use std::sync::{Arc, Mutex};
16
17pub struct SingleThreadedPowGenerator {
18    tracker: Arc<Mutex<JobTracker>>,
19}
20
21impl SingleThreadedPowGenerator {
22    pub fn new() -> Self {
23        Self { tracker: Arc::new(Mutex::new(JobTracker::default())) }
24    }
25}
26
27impl Default for SingleThreadedPowGenerator {
28    fn default() -> Self { Self::new() }
29}
30
31#[async_trait::async_trait]
32impl PowGenerator for SingleThreadedPowGenerator {
33    fn pool_size(&self) -> usize { 1 }
34
35    async fn run_chunk(&self, _slot: usize, chunk_iterations: usize, pow_min: Pow, data_hash: Hash) -> anyhow::Result<(Salt, Pow, Hash)> {
36        pow_generator::run_pool_chunk(chunk_iterations, pow_min, data_hash)
37    }
38
39    fn tracker(&self) -> &Arc<Mutex<JobTracker>> {
40        &self.tracker
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use crate::tools::pow::pow_compute_data_hash;
47    use crate::tools::pow_generator::pow_generator::PowGenerator;
48    use crate::tools::pow_generator::single_threaded_pow_generator::SingleThreadedPowGenerator;
49    use crate::tools::tools;
50    use crate::tools::types::Pow;
51
52    #[tokio::test]
53    async fn single_threaded_generates_valid_pow() -> anyhow::Result<()> {
54        const POW_MIN: Pow = Pow(12);
55        let mut data = [0u8; 64];
56        tools::random_fill_bytes(&mut data);
57        let data_hash = pow_compute_data_hash(&[&data]);
58        let generator = SingleThreadedPowGenerator::new();
59        let (_, pow, _) = generator.generate("test", POW_MIN, data_hash).await?;
60        assert!(pow >= POW_MIN);
61        Ok(())
62    }
63}