Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback to default flags if rxcache initialization fails #3087

Merged
merged 1 commit into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions applications/tari_base_node/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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()),
Expand Down
4 changes: 2 additions & 2 deletions applications/tari_base_node/src/recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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(),
);
Expand Down
89 changes: 61 additions & 28 deletions base_layer/core/src/proof_of_work/randomx_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Mutex<(RandomXVM, RandomXCache, RandomXDataset)>>,
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<Self, RandomXError> {
let flags = RandomXFlag::get_recommended_flags();
let cache = RandomXCache::new(flags, key)?;
fn create(key: &[u8], flags: RandomXFlag) -> Result<Self, RandomXError> {
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,
})
}

Expand All @@ -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))),
}
}

Expand All @@ -82,16 +82,20 @@ impl RandomXFactory {
}

struct RandomXFactoryInner {
// config: RandomXConfig,
flags: RandomXFlag,
vms: HashMap<Vec<u8>, (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,
}
Expand All @@ -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();
}
}