Skip to main content

hashiverse_lib/tools/pow_generator/
native_parallel_pow_generator.rs

1//! Multi-core PoW search for non-WASM targets.
2//!
3//! Each `run_chunk` call runs on a `tokio::task::spawn_blocking` thread; the shared
4//! [`crate::tools::pow_generator::pow_generator::run_pool`] dispatcher fires
5//! `pool_size()` of them concurrently and refeeds whichever slot completes first. With
6//! homogeneous server cores this is roughly equivalent to the previous rayon fan-out;
7//! on heterogeneous CPUs (Apple Silicon P+E, Intel hybrid) it stops fast cores from
8//! idling while a slow core finishes its slice.
9
10#![cfg(not(target_arch = "wasm32"))]
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 NativeParallelPowGenerator {
18    tracker: Arc<Mutex<JobTracker>>,
19}
20
21impl NativeParallelPowGenerator {
22    pub fn new() -> Self {
23        Self { tracker: Arc::new(Mutex::new(JobTracker::default())) }
24    }
25}
26
27impl Default for NativeParallelPowGenerator {
28    fn default() -> Self { Self::new() }
29}
30
31#[async_trait::async_trait]
32impl PowGenerator for NativeParallelPowGenerator {
33    fn pool_size(&self) -> usize {
34        std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
35    }
36
37    async fn run_chunk(&self, _slot: usize, chunk_iterations: usize, pow_min: Pow, data_hash: Hash) -> anyhow::Result<(Salt, Pow, Hash)> {
38        let result = tokio::task::spawn_blocking(move || -> anyhow::Result<(Salt, Pow, Hash)> {
39            pow_generator::run_pool_chunk(chunk_iterations, pow_min, data_hash)
40        })
41        .await??;
42
43        Ok(result)
44    }
45
46    fn tracker(&self) -> &Arc<Mutex<JobTracker>> {
47        &self.tracker
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use crate::tools::pow::pow_compute_data_hash;
54    use crate::tools::pow_generator::native_parallel_pow_generator::NativeParallelPowGenerator;
55    use crate::tools::pow_generator::pow_generator::PowGenerator;
56    use crate::tools::tools;
57    use crate::tools::types::Pow;
58
59    #[tokio::test]
60    async fn native_generates_valid_pow() -> anyhow::Result<()> {
61        const POW_MIN: Pow = Pow(12);
62        let mut data = [0u8; 64];
63        tools::random_fill_bytes(&mut data);
64        let data_hash = pow_compute_data_hash(&[&data]);
65        let generator = NativeParallelPowGenerator::new();
66        let (_, pow, _) = generator.generate("test", POW_MIN, data_hash).await?;
67        assert!(pow >= POW_MIN);
68        Ok(())
69    }
70}