Prechádzať zdrojové kódy

validator/pow: use optimized vm hashing api and an atomic nonce to ensure sequential nonce mining

skoupidi 8 mesiacov pred
rodič
commit
940418cabc
3 zmenil súbory, kde vykonal 28 pridanie a 13 odobranie
  1. 1 1
      Cargo.lock
  2. 15 6
      bin/minerd/src/benchmark.rs
  3. 12 6
      src/validator/pow.rs

+ 1 - 1
Cargo.lock

@@ -5679,7 +5679,7 @@ dependencies = [
 [[package]]
 [[package]]
 name = "randomx"
 name = "randomx"
 version = "1.2.1"
 version = "1.2.1"
-source = "git+https://codeberg.org/darkrenaissance/RandomX#49e59631dbe3db2481c7b0fdf1ae228e822bf05c"
+source = "git+https://codeberg.org/darkrenaissance/RandomX#0e31d5a23983164a171276dea7bea94dc58ca8ed"
 dependencies = [
 dependencies = [
  "bindgen 0.72.1",
  "bindgen 0.72.1",
  "bitflags 2.10.0",
  "bitflags 2.10.0",

+ 15 - 6
bin/minerd/src/benchmark.rs

@@ -16,7 +16,15 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
  */
 
 
-use std::{str::FromStr, thread, time::Instant};
+use std::{
+    str::FromStr,
+    sync::{
+        atomic::{AtomicU64, Ordering},
+        Arc,
+    },
+    thread,
+    time::Instant,
+};
 
 
 use tracing::{error, info};
 use tracing::{error, info};
 
 
@@ -55,19 +63,20 @@ pub fn benchmark(threads: usize, nonces: u64) -> Result<()> {
     // Start mining
     // Start mining
     info!(target: "minerd::benchmark", "Starting mining threads...");
     info!(target: "minerd::benchmark", "Starting mining threads...");
     let mut handles = Vec::with_capacity(vms.len());
     let mut handles = Vec::with_capacity(vms.len());
+    let atomic_nonce = Arc::new(AtomicU64::new(0));
     let threads = vms.len() as u64;
     let threads = vms.len() as u64;
     let mining_start = Instant::now();
     let mining_start = Instant::now();
     for t in 0..threads {
     for t in 0..threads {
         let vm = vms[t as usize].clone();
         let vm = vms[t as usize].clone();
         let mut thread_header = header.clone();
         let mut thread_header = header.clone();
-        thread_header.nonce = t;
+        let atomic_nonce = atomic_nonce.clone();
 
 
         handles.push(thread::spawn(move || {
         handles.push(thread::spawn(move || {
+            thread_header.nonce = atomic_nonce.fetch_add(1, Ordering::SeqCst);
+            vm.calculate_hash_first(thread_header.hash().inner()).unwrap();
             while thread_header.nonce < nonces {
             while thread_header.nonce < nonces {
-                let _ = vm.calculate_hash(thread_header.hash().inner());
-                // This means thread 0 will use nonces, 0, 4, 8, ...
-                // and thread 1 will use nonces, 1, 5, 9, ...
-                thread_header.nonce += threads;
+                thread_header.nonce = atomic_nonce.fetch_add(1, Ordering::SeqCst);
+                let _ = vm.calculate_hash_next(thread_header.hash().inner()).unwrap();
             }
             }
         }));
         }));
     }
     }

+ 12 - 6
src/validator/pow.rs

@@ -546,6 +546,7 @@ pub fn mine_block(
 
 
     debug!(target: "validator::pow::randomx_vms_mine", "[MINER] Initializing mining threads...");
     debug!(target: "validator::pow::randomx_vms_mine", "[MINER] Initializing mining threads...");
     let mut handles = Vec::with_capacity(vms.len());
     let mut handles = Vec::with_capacity(vms.len());
+    let atomic_nonce = Arc::new(AtomicU64::new(0));
     let found_header = Arc::new(AtomicBool::new(false));
     let found_header = Arc::new(AtomicBool::new(false));
     let found_nonce = Arc::new(AtomicU64::new(0));
     let found_nonce = Arc::new(AtomicU64::new(0));
     let threads = vms.len() as u64;
     let threads = vms.len() as u64;
@@ -565,12 +566,18 @@ pub fn mine_block(
         let vm = vms[t as usize].clone();
         let vm = vms[t as usize].clone();
         let target = target.clone();
         let target = target.clone();
         let mut thread_header = header.clone();
         let mut thread_header = header.clone();
-        thread_header.nonce = t;
+        let atomic_nonce = atomic_nonce.clone();
         let found_header = found_header.clone();
         let found_header = found_header.clone();
         let found_nonce = found_nonce.clone();
         let found_nonce = found_nonce.clone();
         let stop_signal = stop_signal.clone();
         let stop_signal = stop_signal.clone();
 
 
         handles.push(thread::spawn(move || {
         handles.push(thread::spawn(move || {
+            let mut last_nonce = atomic_nonce.fetch_add(1, Ordering::SeqCst);
+            thread_header.nonce = last_nonce;
+            if let Err(e) = vm.calculate_hash_first(thread_header.hash().inner()) {
+                error!(target: "validator::pow::randomx_vms_mine", "[MINER] Calculating hash in thread #{t} failed: {e}");
+                return
+            };
             loop {
             loop {
                 // Check if stop signal was received
                 // Check if stop signal was received
                 if stop_signal.is_full() {
                 if stop_signal.is_full() {
@@ -583,7 +590,8 @@ pub fn mine_block(
                     break;
                     break;
                 }
                 }
 
 
-                let out_hash = match vm.calculate_hash(thread_header.hash().inner()) {
+                thread_header.nonce = atomic_nonce.fetch_add(1, Ordering::SeqCst);
+                let out_hash = match vm.calculate_hash_next(thread_header.hash().inner()) {
                     Ok(hash) => hash,
                     Ok(hash) => hash,
                     Err(e) => {
                     Err(e) => {
                         error!(target: "validator::pow::randomx_vms_mine", "[MINER] Calculating hash in thread #{t} failed: {e}");
                         error!(target: "validator::pow::randomx_vms_mine", "[MINER] Calculating hash in thread #{t} failed: {e}");
@@ -593,6 +601,7 @@ pub fn mine_block(
                 let out_hash = BigUint::from_bytes_le(&out_hash);
                 let out_hash = BigUint::from_bytes_le(&out_hash);
                 if out_hash <= target {
                 if out_hash <= target {
                     found_header.store(true, Ordering::SeqCst);
                     found_header.store(true, Ordering::SeqCst);
+                    thread_header.nonce = last_nonce; // Since out hash refers to previous run nonce
                     found_nonce.store(thread_header.nonce, Ordering::SeqCst);
                     found_nonce.store(thread_header.nonce, Ordering::SeqCst);
                     debug!(target: "validator::pow::randomx_vms_mine", "[MINER] Thread #{t} found block header using nonce {}",
                     debug!(target: "validator::pow::randomx_vms_mine", "[MINER] Thread #{t} found block header using nonce {}",
                         thread_header.nonce
                         thread_header.nonce
@@ -601,10 +610,7 @@ pub fn mine_block(
                     debug!(target: "validator::pow::randomx_vms_mine", "[MINER] RandomX output: 0x{out_hash:064x}");
                     debug!(target: "validator::pow::randomx_vms_mine", "[MINER] RandomX output: 0x{out_hash:064x}");
                     break;
                     break;
                 }
                 }
-
-                // This means thread 0 will use nonces, 0, 4, 8, ...
-                // and thread 1 will use nonces, 1, 5, 9, ...
-                thread_header.nonce += threads;
+                last_nonce = thread_header.nonce;
             }
             }
         }));
         }));
     }
     }