diff --git a/applications/tari_base_node/src/builder.rs b/applications/tari_base_node/src/builder.rs index d04ecbe7ba..ce939881ea 100644 --- a/applications/tari_base_node/src/builder.rs +++ b/applications/tari_base_node/src/builder.rs @@ -31,7 +31,7 @@ use tari_core::{ chain_storage::{create_lmdb_database, BlockchainDatabase, BlockchainDatabaseConfig, LMDBDatabase, Validators}, consensus::ConsensusManager, mempool::{service::LocalMempoolService, Mempool, MempoolConfig}, - proof_of_work::randomx_factory::{RandomXConfig, RandomXFactory}, + proof_of_work::randomx_factory::RandomXFactory, transactions::types::CryptoFactories, validation::{ block_validators::{BodyOnlyValidator, OrphanBlockValidator}, @@ -201,7 +201,7 @@ async fn build_node_context( let rules = ConsensusManager::builder(config.network).build(); let factories = CryptoFactories::default(); - let randomx_factory = RandomXFactory::new(RandomXConfig::default(), config.max_randomx_vms); + let randomx_factory = RandomXFactory::new(config.max_randomx_vms); let validators = Validators::new( BodyOnlyValidator::default(), HeaderValidator::new(rules.clone()), diff --git a/applications/tari_base_node/src/recovery.rs b/applications/tari_base_node/src/recovery.rs index d8893a5b80..ce62fe36a3 100644 --- a/applications/tari_base_node/src/recovery.rs +++ b/applications/tari_base_node/src/recovery.rs @@ -42,7 +42,7 @@ use tari_core::{ Validators, }, consensus::ConsensusManager, - proof_of_work::randomx_factory::{RandomXConfig, RandomXFactory}, + proof_of_work::randomx_factory::RandomXFactory, transactions::types::CryptoFactories, validation::{ block_validators::{BodyOnlyValidator, OrphanBlockValidator}, @@ -94,7 +94,7 @@ pub async fn run_recovery(node_config: &GlobalConfig) -> Result<(), anyhow::Erro }; let rules = ConsensusManager::builder(node_config.network).build(); let factories = CryptoFactories::default(); - let randomx_factory = RandomXFactory::new(RandomXConfig::default(), node_config.max_randomx_vms); + let randomx_factory = RandomXFactory::new(node_config.max_randomx_vms); let validators = Validators::new( BodyOnlyValidator::default(), HeaderValidator::new(rules.clone()), diff --git a/base_layer/core/src/base_node/state_machine_service/initializer.rs b/base_layer/core/src/base_node/state_machine_service/initializer.rs index 0402d8849f..a6d4c73a0c 100644 --- a/base_layer/core/src/base_node/state_machine_service/initializer.rs +++ b/base_layer/core/src/base_node/state_machine_service/initializer.rs @@ -34,7 +34,7 @@ use crate::{ }, chain_storage::{async_db::AsyncBlockchainDb, BlockchainBackend}, consensus::ConsensusManager, - proof_of_work::randomx_factory::{RandomXConfig, RandomXFactory}, + proof_of_work::randomx_factory::RandomXFactory, transactions::types::CryptoFactories, }; use log::*; @@ -112,7 +112,7 @@ where B: BlockchainBackend + 'static sync_validators, status_event_sender, state_event_publisher, - RandomXFactory::new(RandomXConfig::default(), max_randomx_vms), + RandomXFactory::new(max_randomx_vms), rules, handles.get_shutdown_signal(), ); 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 2efdc8c9b0..933938a684 100644 --- a/base_layer/core/src/proof_of_work/randomx_factory.rs +++ b/base_layer/core/src/proof_of_work/randomx_factory.rs @@ -9,38 +9,38 @@ use std::{ const LOG_TARGET: &str = "c::pow::randomx_factory"; -#[derive(Default)] -pub struct RandomXConfig { - pub use_large_pages: bool, -} - -impl From<&RandomXConfig> for RandomXFlag { - fn from(source: &RandomXConfig) -> Self { - let mut result = RandomXFlag::get_recommended_flags(); - if source.use_large_pages { - result |= RandomXFlag::FLAG_LARGE_PAGES - } - result - } -} - #[derive(Clone)] pub struct RandomXVMInstance { // Note: If the cache and dataset drops, the vm will be wonky, so have to store all // three for now instance: Arc>, + flags: RandomXFlag, } impl RandomXVMInstance { // Note: Can maybe even get more gains by creating a new VM and sharing the dataset and cache - pub fn new(key: &[u8]) -> Result { - let flags = RandomXFlag::get_recommended_flags(); - let cache = RandomXCache::new(flags, key)?; + 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) + }, + }; + let dataset = RandomXDataset::new(flags, &cache, 0)?; let vm = RandomXVM::new(flags, Some(&cache), Some(&dataset))?; Ok(Self { instance: Arc::new(Mutex::new((vm, cache, dataset))), + flags, }) } @@ -60,14 +60,14 @@ pub struct RandomXFactory { impl Default for RandomXFactory { fn default() -> Self { - Self::new(RandomXConfig::default(), 2) + Self::new(2) } } impl RandomXFactory { - pub fn new(config: RandomXConfig, max_vms: usize) -> Self { + pub fn new(max_vms: usize) -> Self { Self { - inner: Arc::new(RwLock::new(RandomXFactoryInner::new(config, max_vms))), + inner: Arc::new(RwLock::new(RandomXFactoryInner::new(max_vms))), } } @@ -82,16 +82,20 @@ impl RandomXFactory { } struct RandomXFactoryInner { - // config: RandomXConfig, + flags: RandomXFlag, vms: HashMap, (Instant, RandomXVMInstance)>, max_vms: usize, } impl RandomXFactoryInner { - pub fn new(_config: RandomXConfig, max_vms: usize) -> Self { - debug!(target: LOG_TARGET, "RandomX factory started with {} max VMs", max_vms); + pub fn new(max_vms: usize) -> Self { + let flags = RandomXFlag::get_recommended_flags(); + debug!( + target: LOG_TARGET, + "RandomX factory started with {} max VMs and flags = {:?}", max_vms, flags + ); Self { - // config, + flags, vms: Default::default(), max_vms, } @@ -118,12 +122,41 @@ impl RandomXFactoryInner { } } - // TODO: put config in. - - let vm = RandomXVMInstance::new(&key)?; + let vm = RandomXVMInstance::create(&key, self.flags)?; self.vms.insert(Vec::from(key), (Instant::now(), vm.clone())); Ok(vm) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn basic_initialization_and_hash() { + let factory = RandomXFactory::new(2); + + let key = b"some-key"; + let vm = factory.create(&key[..]).unwrap(); + let preimage = b"hashme"; + let hash1 = vm.calculate_hash(&preimage[..]).unwrap(); + let vm = factory.create(&key[..]).unwrap(); + assert_eq!(vm.calculate_hash(&preimage[..]).unwrap(), hash1); + + let key = b"another-key"; + let vm = factory.create(&key[..]).unwrap(); + assert_ne!(vm.calculate_hash(&preimage[..]).unwrap(), hash1); + } + + #[test] + fn large_page_fallback() { + // This only tests the fallback branch on platforms that do not support large pages (e.g. MacOS) + let factory = RandomXFactory::new(1); + factory.inner.write().unwrap().flags = RandomXFlag::FLAG_LARGE_PAGES; + let key = "highly-imaginative-key-name"; + let vm = factory.create(key.as_bytes()).unwrap(); + vm.calculate_hash("hashme".as_bytes()).unwrap(); + } +}