|
@@ -1,6 +1,5 @@
|
|
|
#![allow(non_upper_case_globals)]
|
|
#![allow(non_upper_case_globals)]
|
|
|
#![allow(non_camel_case_types)]
|
|
#![allow(non_camel_case_types)]
|
|
|
-#![allow(non_snake_case)]
|
|
|
|
|
|
|
|
|
|
//! Rust bindings to randomx, a library for computing RandomX hashes.
|
|
//! Rust bindings to randomx, a library for computing RandomX hashes.
|
|
|
//!
|
|
//!
|
|
@@ -22,8 +21,7 @@
|
|
|
|
|
|
|
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
|
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
|
|
|
|
|
|
|
-use std::ptr;
|
|
|
|
|
-use std::sync::Arc;
|
|
|
|
|
|
|
+use std::{ptr, sync::Arc};
|
|
|
|
|
|
|
|
use bitflags::bitflags;
|
|
use bitflags::bitflags;
|
|
|
use libc::{c_ulong, c_void, memcpy};
|
|
use libc::{c_ulong, c_void, memcpy};
|
|
@@ -137,7 +135,7 @@ impl RandomXFlags {
|
|
|
|
|
|
|
|
impl Default for RandomXFlags {
|
|
impl Default for RandomXFlags {
|
|
|
/// Default value for RandomXFlags
|
|
/// Default value for RandomXFlags
|
|
|
- fn default() -> RandomXFlags {
|
|
|
|
|
|
|
+ fn default() -> Self {
|
|
|
RandomXFlags::DEFAULT
|
|
RandomXFlags::DEFAULT
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -178,7 +176,7 @@ impl RandomXCache {
|
|
|
/// * ARGON2_AVX2
|
|
/// * ARGON2_AVX2
|
|
|
///
|
|
///
|
|
|
/// `key` is a sequence of u8 used to initialize SuperScalarHash.
|
|
/// `key` is a sequence of u8 used to initialize SuperScalarHash.
|
|
|
- pub fn new(flags: RandomXFlags, key: &[u8]) -> Result<RandomXCache, RandomXError> {
|
|
|
|
|
|
|
+ pub fn new(flags: RandomXFlags, key: &[u8]) -> Result<Self, RandomXError> {
|
|
|
if key.is_empty() {
|
|
if key.is_empty() {
|
|
|
return Err(RandomXError::ParameterError(
|
|
return Err(RandomXError::ParameterError(
|
|
|
"RandomX cache key is empty".to_string(),
|
|
"RandomX cache key is empty".to_string(),
|
|
@@ -191,7 +189,7 @@ impl RandomXCache {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let inner = RandomXCacheInner { cache_ptr };
|
|
let inner = RandomXCacheInner { cache_ptr };
|
|
|
- let result = RandomXCache {
|
|
|
|
|
|
|
+ let result = Self {
|
|
|
inner: Arc::new(inner),
|
|
inner: Arc::new(inner),
|
|
|
};
|
|
};
|
|
|
let key_ptr = key.as_ptr() as *mut c_void;
|
|
let key_ptr = key.as_ptr() as *mut c_void;
|
|
@@ -209,7 +207,6 @@ impl RandomXCache {
|
|
|
struct RandomXDatasetInner {
|
|
struct RandomXDatasetInner {
|
|
|
dataset_ptr: *mut randomx_dataset,
|
|
dataset_ptr: *mut randomx_dataset,
|
|
|
dataset_count: u32,
|
|
dataset_count: u32,
|
|
|
- #[allow(dead_code)]
|
|
|
|
|
cache: RandomXCache,
|
|
cache: RandomXCache,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -233,8 +230,8 @@ pub struct RandomXDataset {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl RandomXDataset {
|
|
impl RandomXDataset {
|
|
|
- /// Creates a new dataset object, allocates memory to the `dataset` object
|
|
|
|
|
- /// and initializes it.
|
|
|
|
|
|
|
+ /// Creates a new dataset object and allocates memory to the
|
|
|
|
|
+ /// `dataset` object. Dataset must be initialized afterwards.
|
|
|
///
|
|
///
|
|
|
/// `flags` is one of the following:
|
|
/// `flags` is one of the following:
|
|
|
/// * DEFAULT
|
|
/// * DEFAULT
|
|
@@ -242,20 +239,13 @@ impl RandomXDataset {
|
|
|
///
|
|
///
|
|
|
/// `cache` is a cache object.
|
|
/// `cache` is a cache object.
|
|
|
///
|
|
///
|
|
|
- /// `start_item` is the item number where initialization should start,
|
|
|
|
|
- /// recommended to pass in 0.
|
|
|
|
|
- ///
|
|
|
|
|
/// `item_count` is the total item count in the dataset, it can be
|
|
/// `item_count` is the total item count in the dataset, it can be
|
|
|
/// retrieved with `RandomXDataset::count()`.
|
|
/// retrieved with `RandomXDataset::count()`.
|
|
|
- ///
|
|
|
|
|
- /// Conversions may be lossy on Windows or Linux.
|
|
|
|
|
- #[allow(clippy::useless_conversion)]
|
|
|
|
|
pub fn new(
|
|
pub fn new(
|
|
|
flags: RandomXFlags,
|
|
flags: RandomXFlags,
|
|
|
cache: RandomXCache,
|
|
cache: RandomXCache,
|
|
|
- start_item: u32,
|
|
|
|
|
item_count: u32,
|
|
item_count: u32,
|
|
|
- ) -> Result<RandomXDataset, RandomXError> {
|
|
|
|
|
|
|
+ ) -> Result<Self, RandomXError> {
|
|
|
let test = unsafe { randomx_alloc_dataset(flags.bits()) };
|
|
let test = unsafe { randomx_alloc_dataset(flags.bits()) };
|
|
|
if test.is_null() {
|
|
if test.is_null() {
|
|
|
return Err(RandomXError::DatasetAllocError);
|
|
return Err(RandomXError::DatasetAllocError);
|
|
@@ -267,25 +257,63 @@ impl RandomXDataset {
|
|
|
cache,
|
|
cache,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- let result = RandomXDataset {
|
|
|
|
|
|
|
+ Ok(Self {
|
|
|
inner: Arc::new(inner),
|
|
inner: Arc::new(inner),
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- /*
|
|
|
|
|
- if start_item >= item_count {
|
|
|
|
|
- return Err(RandomXError::DatasetAllocError);
|
|
|
|
|
- }
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ /// Initializes the dataset object.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `start_item` is the item number where initialization should
|
|
|
|
|
+ /// start.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `item_count` is the total item count in the dataset, it can be
|
|
|
|
|
+ /// retrieved with `RandomXDataset::count()`.
|
|
|
|
|
+ pub fn init(&self, start_item: u32, item_count: u32) {
|
|
|
unsafe {
|
|
unsafe {
|
|
|
randomx_init_dataset(
|
|
randomx_init_dataset(
|
|
|
- result.inner.dataset_ptr,
|
|
|
|
|
- result.inner.cache.inner.cache_ptr,
|
|
|
|
|
|
|
+ self.inner.dataset_ptr,
|
|
|
|
|
+ self.inner.cache.inner.cache_ptr,
|
|
|
c_ulong::from(start_item),
|
|
c_ulong::from(start_item),
|
|
|
c_ulong::from(item_count),
|
|
c_ulong::from(item_count),
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
- Ok(result)
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Creates a new dataset object, allocates memory to the `dataset` object
|
|
|
|
|
+ /// and initializes it.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `flags` is one of the following:
|
|
|
|
|
+ /// * DEFAULT
|
|
|
|
|
+ /// * LARGEPAGES
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `cache` is a cache object.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `start_item` is the item number where initialization should start,
|
|
|
|
|
+ /// recommended to pass in 0.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `item_count` is the total item count in the dataset, it can be
|
|
|
|
|
+ /// retrieved with `RandomXDataset::count()`.
|
|
|
|
|
+ pub fn new_init(
|
|
|
|
|
+ flags: RandomXFlags,
|
|
|
|
|
+ cache: RandomXCache,
|
|
|
|
|
+ start_item: u32,
|
|
|
|
|
+ item_count: u32,
|
|
|
|
|
+ ) -> Result<Self, RandomXError> {
|
|
|
|
|
+ let dataset = Self::new(flags, cache, item_count)?;
|
|
|
|
|
+ dataset.init(start_item, item_count);
|
|
|
|
|
+ Ok(dataset)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Creates a new dataset subset and initializes it.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `start_item` is the item number where initialization should start.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// `item_count` is the total item count in the subset.
|
|
|
|
|
+ pub fn subset_init(&self, start_item: u32, item_count: u32) -> Self {
|
|
|
|
|
+ let subset = self.clone();
|
|
|
|
|
+ subset.init(start_item, item_count);
|
|
|
|
|
+ subset
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// Returns the number of items in the `dataset` or an error on failure.
|
|
/// Returns the number of items in the `dataset` or an error on failure.
|
|
@@ -370,7 +398,7 @@ impl RandomXVM {
|
|
|
flags: RandomXFlags,
|
|
flags: RandomXFlags,
|
|
|
cache: Option<RandomXCache>,
|
|
cache: Option<RandomXCache>,
|
|
|
dataset: Option<RandomXDataset>,
|
|
dataset: Option<RandomXDataset>,
|
|
|
- ) -> Result<RandomXVM, RandomXError> {
|
|
|
|
|
|
|
+ ) -> Result<Self, RandomXError> {
|
|
|
let is_full_mem = flags.contains(RandomXFlags::FULLMEM);
|
|
let is_full_mem = flags.contains(RandomXFlags::FULLMEM);
|
|
|
|
|
|
|
|
match (cache, dataset) {
|
|
match (cache, dataset) {
|
|
@@ -389,7 +417,7 @@ impl RandomXVM {
|
|
|
|
|
|
|
|
let vm = unsafe { randomx_create_vm(flags.bits(), cache_ptr, dataset_ptr) };
|
|
let vm = unsafe { randomx_create_vm(flags.bits(), cache_ptr, dataset_ptr) };
|
|
|
|
|
|
|
|
- Ok(RandomXVM {
|
|
|
|
|
|
|
+ Ok(Self {
|
|
|
vm,
|
|
vm,
|
|
|
flags,
|
|
flags,
|
|
|
linked_cache: cache,
|
|
linked_cache: cache,
|
|
@@ -486,9 +514,8 @@ impl RandomXVM {
|
|
|
|
|
|
|
|
// Not len() as last iteration assigns final hash
|
|
// Not len() as last iteration assigns final hash
|
|
|
let iterations = input.len() + 1;
|
|
let iterations = input.len() + 1;
|
|
|
-
|
|
|
|
|
- #[allow(clippy::needless_range_loop)]
|
|
|
|
|
- for i in 0..iterations {
|
|
|
|
|
|
|
+ let mut i = 0;
|
|
|
|
|
+ while i < iterations {
|
|
|
if i == iterations - 1 {
|
|
if i == iterations - 1 {
|
|
|
// For last iteration
|
|
// For last iteration
|
|
|
unsafe {
|
|
unsafe {
|
|
@@ -533,6 +560,8 @@ impl RandomXVM {
|
|
|
let output: Vec<u8> = arr.to_vec();
|
|
let output: Vec<u8> = arr.to_vec();
|
|
|
result.push(output);
|
|
result.push(output);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ i += 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Ok(result)
|
|
Ok(result)
|
|
@@ -541,7 +570,7 @@ impl RandomXVM {
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
mod tests {
|
|
|
- use super::*;
|
|
|
|
|
|
|
+ use crate::{RandomXCache, RandomXDataset, RandomXFlags, RandomXVM};
|
|
|
|
|
|
|
|
#[test]
|
|
#[test]
|
|
|
fn lib_alloc_cache() {
|
|
fn lib_alloc_cache() {
|
|
@@ -557,7 +586,7 @@ mod tests {
|
|
|
let key = "Key";
|
|
let key = "Key";
|
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset =
|
|
let dataset =
|
|
|
- RandomXDataset::new(flags, cache.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
.expect("Failed to allocate dataset");
|
|
.expect("Failed to allocate dataset");
|
|
|
drop(dataset);
|
|
drop(dataset);
|
|
|
drop(cache);
|
|
drop(cache);
|
|
@@ -572,7 +601,8 @@ mod tests {
|
|
|
RandomXVM::new(flags, Some(cache.clone()), None).expect("Failed to allocate VM");
|
|
RandomXVM::new(flags, Some(cache.clone()), None).expect("Failed to allocate VM");
|
|
|
drop(vm);
|
|
drop(vm);
|
|
|
let dataset =
|
|
let dataset =
|
|
|
- RandomXDataset::new(flags, cache.clone(), 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
+ .unwrap();
|
|
|
vm = RandomXVM::new(flags, Some(cache.clone()), Some(dataset.clone()))
|
|
vm = RandomXVM::new(flags, Some(cache.clone()), Some(dataset.clone()))
|
|
|
.expect("Failed to allocate VM");
|
|
.expect("Failed to allocate VM");
|
|
|
drop(dataset);
|
|
drop(dataset);
|
|
@@ -586,7 +616,8 @@ mod tests {
|
|
|
let key = "Key";
|
|
let key = "Key";
|
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset =
|
|
let dataset =
|
|
|
- RandomXDataset::new(flags, cache.clone(), 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
+ .unwrap();
|
|
|
let memory = dataset.get_data().unwrap_or_else(|_| Vec::new());
|
|
let memory = dataset.get_data().unwrap_or_else(|_| Vec::new());
|
|
|
assert!(!memory.is_empty(), "Failed to get dataset memory");
|
|
assert!(!memory.is_empty(), "Failed to get dataset memory");
|
|
|
let v = vec![0u8; memory.len()];
|
|
let v = vec![0u8; memory.len()];
|
|
@@ -619,7 +650,7 @@ mod tests {
|
|
|
|
|
|
|
|
let cache3 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache3 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset3 =
|
|
let dataset3 =
|
|
|
- RandomXDataset::new(flags, cache3.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache3.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
.unwrap();
|
|
.unwrap();
|
|
|
let mut vm3 = RandomXVM::new(flags2, None, Some(dataset3.clone())).unwrap();
|
|
let mut vm3 = RandomXVM::new(flags2, None, Some(dataset3.clone())).unwrap();
|
|
|
let hash4 = vm3.calculate_hash(input.as_bytes()).expect("no data");
|
|
let hash4 = vm3.calculate_hash(input.as_bytes()).expect("no data");
|
|
@@ -631,7 +662,7 @@ mod tests {
|
|
|
|
|
|
|
|
let cache4 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache4 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset4 =
|
|
let dataset4 =
|
|
|
- RandomXDataset::new(flags, cache4.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache4.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
.unwrap();
|
|
.unwrap();
|
|
|
let vm4 = RandomXVM::new(flags2, Some(cache4), Some(dataset4.clone())).unwrap();
|
|
let vm4 = RandomXVM::new(flags2, Some(cache4), Some(dataset4.clone())).unwrap();
|
|
|
let hash6 = vm3.calculate_hash(input.as_bytes()).expect("no data");
|
|
let hash6 = vm3.calculate_hash(input.as_bytes()).expect("no data");
|
|
@@ -681,7 +712,8 @@ mod tests {
|
|
|
let input = "Input";
|
|
let input = "Input";
|
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset =
|
|
let dataset =
|
|
|
- RandomXDataset::new(flags, cache.clone(), 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
+ .unwrap();
|
|
|
let vm = RandomXVM::new(flags, Some(cache.clone()), Some(dataset.clone())).unwrap();
|
|
let vm = RandomXVM::new(flags, Some(cache.clone()), Some(dataset.clone())).unwrap();
|
|
|
let hash = vm.calculate_hash(input.as_bytes()).expect("no data");
|
|
let hash = vm.calculate_hash(input.as_bytes()).expect("no data");
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
@@ -697,7 +729,7 @@ mod tests {
|
|
|
|
|
|
|
|
let cache1 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache1 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset1 =
|
|
let dataset1 =
|
|
|
- RandomXDataset::new(flags, cache1.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache1.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
.unwrap();
|
|
.unwrap();
|
|
|
let vm1 = RandomXVM::new(flags, Some(cache1.clone()), Some(dataset1.clone())).unwrap();
|
|
let vm1 = RandomXVM::new(flags, Some(cache1.clone()), Some(dataset1.clone())).unwrap();
|
|
|
let hash1 = vm1.calculate_hash(input.as_bytes()).expect("no data");
|
|
let hash1 = vm1.calculate_hash(input.as_bytes()).expect("no data");
|
|
@@ -720,7 +752,8 @@ mod tests {
|
|
|
let input = "Input";
|
|
let input = "Input";
|
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset =
|
|
let dataset =
|
|
|
- RandomXDataset::new(flags, cache.clone(), 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
+ .unwrap();
|
|
|
let vm = RandomXVM::new(flags, Some(cache.clone()), Some(dataset.clone())).unwrap();
|
|
let vm = RandomXVM::new(flags, Some(cache.clone()), Some(dataset.clone())).unwrap();
|
|
|
drop(dataset);
|
|
drop(dataset);
|
|
|
drop(cache);
|
|
drop(cache);
|
|
@@ -736,7 +769,7 @@ mod tests {
|
|
|
|
|
|
|
|
let cache1 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
let cache1 = RandomXCache::new(flags, key.as_bytes()).unwrap();
|
|
|
let dataset1 =
|
|
let dataset1 =
|
|
|
- RandomXDataset::new(flags, cache1.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache1.clone(), 0, RandomXDataset::count().unwrap())
|
|
|
.unwrap();
|
|
.unwrap();
|
|
|
let vm1 = RandomXVM::new(flags, Some(cache1.clone()), Some(dataset1.clone())).unwrap();
|
|
let vm1 = RandomXVM::new(flags, Some(cache1.clone()), Some(dataset1.clone())).unwrap();
|
|
|
drop(dataset1);
|
|
drop(dataset1);
|
|
@@ -761,7 +794,7 @@ mod tests {
|
|
|
let cache = RandomXCache::new(flags, key).unwrap();
|
|
let cache = RandomXCache::new(flags, key).unwrap();
|
|
|
|
|
|
|
|
let dataset =
|
|
let dataset =
|
|
|
- RandomXDataset::new(flags, cache, 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache, 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
|
let fast_vm = RandomXVM::new(flags, None, Some(dataset)).unwrap();
|
|
let fast_vm = RandomXVM::new(flags, None, Some(dataset)).unwrap();
|
|
|
|
|
|
|
@@ -797,7 +830,7 @@ mod tests {
|
|
|
let cache = RandomXCache::new(flags, key).unwrap();
|
|
let cache = RandomXCache::new(flags, key).unwrap();
|
|
|
|
|
|
|
|
let dataset =
|
|
let dataset =
|
|
|
- RandomXDataset::new(flags, cache, 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
+ RandomXDataset::new_init(flags, cache, 0, RandomXDataset::count().unwrap()).unwrap();
|
|
|
|
|
|
|
|
let vm = RandomXVM::new(flags, None, Some(dataset)).unwrap();
|
|
let vm = RandomXVM::new(flags, None, Some(dataset)).unwrap();
|
|
|
|
|
|