|
@@ -488,6 +488,65 @@ impl RandomXVM {
|
|
|
Ok(arr.to_vec())
|
|
Ok(arr.to_vec())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ pub fn calculate_hash_first(&self, input: &[u8]) -> Result<(), RandomXError> {
|
|
|
|
|
+ if input.is_empty() {
|
|
|
|
|
+ return Err(RandomXError::ParameterError(
|
|
|
|
|
+ "RandomX VM input empty".to_string(),
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let input_size = input.len();
|
|
|
|
|
+ let input_ptr = input.as_ptr() as *mut c_void;
|
|
|
|
|
+
|
|
|
|
|
+ unsafe {
|
|
|
|
|
+ randomx_calculate_hash_first(self.vm, input_ptr, input_size);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn calculate_hash_next(&self, input: &[u8]) -> Result<Vec<u8>, RandomXError> {
|
|
|
|
|
+ if input.is_empty() {
|
|
|
|
|
+ return Err(RandomXError::ParameterError(
|
|
|
|
|
+ "RandomX VM input empty".to_string(),
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let input_size = input.len();
|
|
|
|
|
+ let input_ptr = input.as_ptr() as *mut c_void;
|
|
|
|
|
+ let arr = [0; RANDOMX_HASH_SIZE as usize];
|
|
|
|
|
+ let output_ptr = arr.as_ptr() as *mut c_void;
|
|
|
|
|
+
|
|
|
|
|
+ unsafe {
|
|
|
|
|
+ randomx_calculate_hash_next(self.vm, input_ptr, input_size, output_ptr);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if arr == [0; RANDOMX_HASH_SIZE as usize] {
|
|
|
|
|
+ return Err(RandomXError::Other(
|
|
|
|
|
+ "RandomX calculated hash was empty".to_string(),
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Ok(arr.to_vec())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn calculate_hash_last(&self) -> Result<Vec<u8>, RandomXError> {
|
|
|
|
|
+ let arr = [0; RANDOMX_HASH_SIZE as usize];
|
|
|
|
|
+ let output_ptr = arr.as_ptr() as *mut c_void;
|
|
|
|
|
+
|
|
|
|
|
+ unsafe {
|
|
|
|
|
+ randomx_calculate_hash_last(self.vm, output_ptr);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if arr == [0; RANDOMX_HASH_SIZE as usize] {
|
|
|
|
|
+ return Err(RandomXError::Other(
|
|
|
|
|
+ "RandomX calculated hash was empty".to_string(),
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Ok(arr.to_vec())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/// Calculates hashes from a set of inputs.
|
|
/// Calculates hashes from a set of inputs.
|
|
|
///
|
|
///
|
|
|
/// `input` is an array of a sequence of u8 to be hashed.
|
|
/// `input` is an array of a sequence of u8 to be hashed.
|
|
@@ -568,6 +627,39 @@ impl RandomXVM {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/// Calculate a RandomX commitment from a RandomX hash and its input.
|
|
|
|
|
+pub fn calculate_commitment(
|
|
|
|
|
+ input: &[u8],
|
|
|
|
|
+ hash: &[u8],
|
|
|
|
|
+ output: &mut [u8],
|
|
|
|
|
+) -> Result<(), RandomXError> {
|
|
|
|
|
+ if hash.len() != RANDOMX_HASH_SIZE as usize {
|
|
|
|
|
+ return Err(RandomXError::ParameterError(format!(
|
|
|
|
|
+ "Hash must be {} bytes, got {}",
|
|
|
|
|
+ RANDOMX_HASH_SIZE,
|
|
|
|
|
+ hash.len()
|
|
|
|
|
+ )));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if output.len() != RANDOMX_HASH_SIZE as usize {
|
|
|
|
|
+ return Err(RandomXError::ParameterError(format!(
|
|
|
|
|
+ "Output must be {} bytes, got {}",
|
|
|
|
|
+ RANDOMX_HASH_SIZE,
|
|
|
|
|
+ hash.len()
|
|
|
|
|
+ )));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let input_ptr = input.as_ptr() as *const c_void;
|
|
|
|
|
+ let hash_ptr = hash.as_ptr() as *const c_void;
|
|
|
|
|
+ let output_ptr = output.as_ptr() as *mut c_void;
|
|
|
|
|
+
|
|
|
|
|
+ unsafe {
|
|
|
|
|
+ randomx_calculate_commitment(input_ptr, input.len(), hash_ptr, output_ptr);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[cfg(test)]
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
mod tests {
|
|
|
use crate::{RandomXCache, RandomXDataset, RandomXFlags, RandomXVM};
|
|
use crate::{RandomXCache, RandomXDataset, RandomXFlags, RandomXVM};
|