darkfi/validator/
randomx_factory.rs1use std::{collections::HashMap, sync::Arc, time::Instant};
21
22use randomx::{RandomXCache, RandomXFlags, RandomXVM};
23use tracing::{debug, warn};
24
25use crate::Result;
26
27pub type RandomXVMInstance = Arc<RandomXVM>;
29
30#[derive(Clone, Debug)]
32pub struct RandomXFactory {
33 vms: HashMap<Vec<u8>, (Instant, RandomXVMInstance)>,
34 max_vms: usize,
35}
36
37impl Default for RandomXFactory {
38 fn default() -> Self {
39 Self::new(2)
40 }
41}
42
43impl RandomXFactory {
44 pub fn new(max_vms: usize) -> Self {
47 Self { vms: HashMap::new(), max_vms }
48 }
49
50 pub fn create(&mut self, key: &[u8]) -> Result<RandomXVMInstance> {
52 if let Some(entry) = self.vms.get_mut(key) {
53 let vm = entry.1.clone();
54 entry.0 = Instant::now();
55 return Ok(vm)
56 }
57
58 if self.vms.len() >= self.max_vms {
59 if let Some(oldest_key) =
60 self.vms.iter().min_by_key(|(_, (i, _))| *i).map(|(k, _)| k.clone())
61 {
62 self.vms.remove(&oldest_key);
63 }
64 }
65
66 let flags = RandomXFlags::get_recommended_flags();
69 let (flags, cache) = match RandomXCache::new(flags, key) {
70 Ok(cache) => (flags, cache),
71 Err(err) => {
72 warn!(target: "validator::randomx", "[VALIDATOR] Error initializing RandomX cache with flags {flags:?}: {err}");
73 warn!(target: "validator::randomx", "[VALIDATOR] Falling back to default flags");
74 let flags = RandomXFlags::DEFAULT;
75 let cache = RandomXCache::new(flags, key)?;
76 (flags, cache)
77 }
78 };
79
80 let vm = Arc::new(RandomXVM::new(flags, Some(cache), None)?);
81 debug!(target: "validator::randomx", "[VALIDATOR] RandomX VM started with flags = {flags:?}");
82
83 self.vms.insert(Vec::from(key), (Instant::now(), vm.clone()));
84 Ok(vm)
85 }
86
87 pub fn get_count(&self) -> usize {
90 self.vms.len()
91 }
92}