From 825ca06fa29fda0e66c34fe94640797e4deb0776 Mon Sep 17 00:00:00 2001 From: Brian Pearce Date: Fri, 6 Sep 2024 16:40:22 +0200 Subject: [PATCH] feat: changes for the randomx miner (#6537) Description --- Minor changes of interface needed for the randomx miner. Motivation and Context --- So the randomx miner can work mo' betta How Has This Been Tested? --- Tested alongside the miner locally. --- .../src/proof_of_work/monero_rx/helpers.rs | 4 +- .../proof_of_work/monero_rx/merkle_tree.rs | 2 +- .../src/proof_of_work/monero_rx/pow_data.rs | 2 +- .../core/src/proof_of_work/randomx_factory.rs | 91 ++++++++++--------- 4 files changed, 54 insertions(+), 45 deletions(-) diff --git a/base_layer/core/src/proof_of_work/monero_rx/helpers.rs b/base_layer/core/src/proof_of_work/monero_rx/helpers.rs index 5b0dae7ea6..100e09c4b7 100644 --- a/base_layer/core/src/proof_of_work/monero_rx/helpers.rs +++ b/base_layer/core/src/proof_of_work/monero_rx/helpers.rs @@ -65,7 +65,7 @@ pub fn randomx_difficulty( let monero_pow_data = verify_header(header, genesis_block_hash, consensus)?; trace!(target: LOG_TARGET, "Valid Monero data: {}", monero_pow_data); let blockhashing_blob = monero_pow_data.to_blockhashing_blob(); - let vm = randomx_factory.create(monero_pow_data.randomx_key())?; + let vm = randomx_factory.create(monero_pow_data.randomx_key(), None, None)?; get_random_x_difficulty(&blockhashing_blob, &vm).map(|(diff, _)| diff) } @@ -1245,7 +1245,7 @@ mod test { let key = from_hex("2aca6501719a5c7ab7d4acbc7cc5d277b57ad8c27c6830788c2d5a596308e5b1").unwrap(); let rx = RandomXFactory::default(); - let (difficulty, hash) = get_random_x_difficulty(&input, &rx.create(&key).unwrap()).unwrap(); + let (difficulty, hash) = get_random_x_difficulty(&input, &rx.create(&key, None, None).unwrap()).unwrap(); assert_eq!( hash.to_hex(), "f68fbc8cc85bde856cd1323e9f8e6f024483038d728835de2f8c014ff6260000" diff --git a/base_layer/core/src/proof_of_work/monero_rx/merkle_tree.rs b/base_layer/core/src/proof_of_work/monero_rx/merkle_tree.rs index faaeeba537..93184fa968 100644 --- a/base_layer/core/src/proof_of_work/monero_rx/merkle_tree.rs +++ b/base_layer/core/src/proof_of_work/monero_rx/merkle_tree.rs @@ -423,7 +423,7 @@ mod test { fn randomx_hash(input: &[u8], key: &str) -> String { let key = from_hex(key).unwrap(); RandomXFactory::default() - .create(&key) + .create(&key, None, None) .unwrap() .calculate_hash(input) .unwrap() diff --git a/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs b/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs index 14ebf802e0..23b9131967 100644 --- a/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs +++ b/base_layer/core/src/proof_of_work/monero_rx/pow_data.rs @@ -47,7 +47,7 @@ use crate::{ proof_of_work::monero_rx::helpers::create_block_hashing_blob, }; -/// This is a struct to deserialize the data from he pow field into data required for the randomX Monero merged mine +/// This is a struct to deserialize the data from the pow field into data required for the randomX Monero merged mine /// pow. #[derive(Clone, Debug)] pub struct MoneroPowData { diff --git a/base_layer/core/src/proof_of_work/randomx_factory.rs b/base_layer/core/src/proof_of_work/randomx_factory.rs index fb4889d3fa..4f96871f0f 100644 --- a/base_layer/core/src/proof_of_work/randomx_factory.rs +++ b/base_layer/core/src/proof_of_work/randomx_factory.rs @@ -9,7 +9,7 @@ use std::{ }; use log::*; -use randomx_rs::{RandomXCache, RandomXError, RandomXFlag, RandomXVM}; +use randomx_rs::{RandomXCache, RandomXDataset, RandomXError, RandomXFlag, RandomXVM}; const LOG_TARGET: &str = "c::pow::randomx_factory"; @@ -35,32 +35,21 @@ pub struct RandomXVMInstance { } impl RandomXVMInstance { - fn create(key: &[u8], flags: RandomXFlag) -> Result { - let (flags, cache) = match RandomXCache::new(flags, key) { - Ok(cache) => (flags, cache), - Err(err) => { - warn!( - target: LOG_TARGET, - "Error initializing RandomX cache with flags {:?}. {:?}. Fallback to default flags", flags, err - ); - // This is informed by how RandomX falls back on any cache allocation failure - // https://github.com/xmrig/xmrig/blob/02b2b87bb685ab83b132267aa3c2de0766f16b8b/src/crypto/rx/RxCache.cpp#L88 - let flags = RandomXFlag::FLAG_DEFAULT; - let cache = RandomXCache::new(flags, key)?; - (flags, cache) - }, - }; - + fn create( + key: &[u8], + flags: RandomXFlag, + cache: Option, + dataset: Option, + ) -> Result { // Note: Memory required per VM in light mode is 256MB - let vm = RandomXVM::new(flags, Some(cache), None)?; - - // Note: No dataset is initialized here because we want to run in light mode. Only a cache - // is required by the VM for verification, giving it a dataset will only make the VM - // consume more memory than necessary. Dataset is currently an optional value as it may be - // useful at some point in future. // Note: RandomXFlag::FULL_MEM and RandomXFlag::LARGE_PAGES are incompatible with // light mode. These are not set by RandomX automatically even in fast mode. + let cache = match cache { + Some(c) => c, + None => RandomXCache::new(flags, key)?, + }; + let vm = RandomXVM::new(flags, Some(cache), dataset)?; Ok(Self { #[allow(clippy::arc_with_non_send_sync)] @@ -106,15 +95,26 @@ impl RandomXFactory { } } + pub fn new_with_flags(max_vms: usize, flags: RandomXFlag) -> Self { + Self { + inner: Arc::new(RwLock::new(RandomXFactoryInner::new_with_flags(max_vms, flags))), + } + } + /// Create a new RandomX VM instance with the specified key - pub fn create(&self, key: &[u8]) -> Result { + pub fn create( + &self, + key: &[u8], + cache: Option, + dataset: Option, + ) -> Result { let res; { let mut inner = self .inner .write() .map_err(|_| RandomXVMFactoryError::PoisonedLockError)?; - res = inner.create(key)?; + res = inner.create(key, cache, dataset)?; } Ok(res) } @@ -158,8 +158,25 @@ impl RandomXFactoryInner { } } + pub(crate) fn new_with_flags(max_vms: usize, flags: RandomXFlag) -> Self { + debug!( + target: LOG_TARGET, + "RandomX factory started with {} max VMs and recommended flags = {:?}", max_vms, flags + ); + Self { + flags, + vms: Default::default(), + max_vms, + } + } + /// Create a new RandomXVMInstance - pub(crate) fn create(&mut self, key: &[u8]) -> Result { + pub(crate) fn create( + &mut self, + key: &[u8], + cache: Option, + dataset: Option, + ) -> Result { if let Some(entry) = self.vms.get_mut(key) { let vm = entry.1.clone(); entry.0 = Instant::now(); @@ -167,20 +184,12 @@ impl RandomXFactoryInner { } if self.vms.len() >= self.max_vms { - let mut oldest_value = Instant::now(); - let mut oldest_key = None; - for (k, v) in &self.vms { - if v.0 < oldest_value { - oldest_key = Some(k.clone()); - oldest_value = v.0; - } - } - if let Some(k) = oldest_key { - self.vms.remove(&k); + if let Some(oldest_key) = self.vms.iter().min_by_key(|(_, (i, _))| *i).map(|(k, _)| k.clone()) { + self.vms.remove(&oldest_key); } } - let vm = RandomXVMInstance::create(key, self.flags)?; + let vm = RandomXVMInstance::create(key, self.flags, cache, dataset)?; self.vms.insert(Vec::from(key), (Instant::now(), vm.clone())); @@ -216,14 +225,14 @@ mod test { let factory = RandomXFactory::new(2); let key = b"some-key"; - let vm = factory.create(&key[..]).unwrap(); + let vm = factory.create(&key[..], None, None).unwrap(); let preimage = b"hashme"; let hash1 = vm.calculate_hash(&preimage[..]).unwrap(); - let vm = factory.create(&key[..]).unwrap(); + let vm = factory.create(&key[..], None, None).unwrap(); assert_eq!(vm.calculate_hash(&preimage[..]).unwrap(), hash1); let key = b"another-key"; - let vm = factory.create(&key[..]).unwrap(); + let vm = factory.create(&key[..], None, None).unwrap(); assert_ne!(vm.calculate_hash(&preimage[..]).unwrap(), hash1); } @@ -236,7 +245,7 @@ mod test { let factory = factory.clone(); threads.push(tokio::spawn(async move { let key = b"some-key"; - let vm = factory.create(&key[..]).unwrap(); + let vm = factory.create(&key[..], None, None).unwrap(); let preimage = b"hashme"; let _hash = vm.calculate_hash(&preimage[..]).unwrap(); }));