2023-09-05 10:56:07 +00:00
|
|
|
#[link(name = "cryptonight")]
|
|
|
|
extern "C" {
|
|
|
|
fn cn_slow_hash(
|
|
|
|
data: *const u8,
|
|
|
|
length: usize,
|
|
|
|
hash: *mut u8,
|
|
|
|
variant: i32,
|
|
|
|
pre_hashed: i32,
|
|
|
|
height: u64,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CryptoNight variants used in Monero, with data needed for specific variants.
|
|
|
|
pub enum Variant {
|
|
|
|
V0,
|
|
|
|
V1,
|
|
|
|
V2,
|
2023-09-07 20:24:33 +00:00
|
|
|
R { height: u64 },
|
2023-09-05 10:56:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Variant {
|
|
|
|
/// Returns the height of the block we are hashing, if thats relevant for this variant otherwise
|
|
|
|
/// `0` is returned.
|
|
|
|
fn height(&self) -> u64 {
|
2023-09-07 20:24:33 +00:00
|
|
|
if let Variant::R { height } = self {
|
2023-09-05 10:56:07 +00:00
|
|
|
*height
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn identifier(&self) -> i32 {
|
|
|
|
match self {
|
|
|
|
Variant::V0 => 0,
|
|
|
|
Variant::V1 => 1,
|
|
|
|
Variant::V2 => 2,
|
2023-09-07 20:24:33 +00:00
|
|
|
Variant::R { .. } => 4,
|
2023-09-05 10:56:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Calculates the CryptoNight variant hash of buf.
|
|
|
|
pub fn cryptonight_hash(buf: &[u8], variant: &Variant) -> [u8; 32] {
|
|
|
|
let mut hash = [0; 32];
|
|
|
|
unsafe {
|
|
|
|
cn_slow_hash(
|
|
|
|
buf.as_ptr(),
|
|
|
|
buf.len(),
|
|
|
|
hash.as_mut_ptr(),
|
|
|
|
variant.identifier(),
|
|
|
|
0,
|
|
|
|
variant.height(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
hash
|
|
|
|
}
|