cryptonote_raw_crypto/
hash.rs

1extern "C" {
2  fn cn_slow_hash(data: *const u8, length: usize, hash: *mut u8, variant: usize, prehashed: usize);
3  fn cn_fast_hash(data: *const u8, length: usize, hash: *mut u8);
4  fn check_hash(hash: *const [u8; 32], difficulty: u64) -> bool;
5}
6
7pub struct Hash {}
8
9impl Hash {
10  pub fn fast(data: &[u8]) -> [u8; 32] {
11    let mut hash: [u8; 32] = [0; 32];
12    unsafe { cn_fast_hash(data.as_ptr(), data.len(), hash.as_mut_ptr()) }
13    hash
14  }
15  pub fn slow(input: &[u8]) -> [u8; 32] {
16    return Hash::slow_with_variant(input, 0);
17  }
18
19  pub fn slow_with_variant(input: &[u8], variant: usize) -> [u8; 32] {
20    let mut hash: [u8; 32] = [0; 32];
21    unsafe {
22      cn_slow_hash(input.as_ptr(), input.len(), hash.as_mut_ptr(), variant, 0);
23    }
24    hash
25  }
26
27  pub fn check_with_difficulty(hash: &[u8; 32], difficulty: u64) -> bool {
28    unsafe {
29      return check_hash(hash, difficulty);
30    }
31  }
32}
33
34#[cfg(test)]
35mod tests {
36  use super::*;
37  use std::fs::{canonicalize, File};
38  use std::io::{prelude::*, BufReader};
39  use std::path::PathBuf;
40
41  #[test]
42  fn should_check_hash_with_difficulty() {
43    assert!(Hash::check_with_difficulty(
44      &[
45        0, 223, 74, 253, 65, 221, 188, 172, 253, 50, 122, 246, 173, 212, 162, 103, 13, 174, 254,
46        199, 175, 49, 254, 177, 181, 91, 56, 9, 98, 1, 0, 0
47      ],
48      10343869
49    ));
50  }
51
52  #[test]
53
54  fn should_test_fast() {
55    let path = PathBuf::from("./tests/tests-fast.txt");
56    let str = canonicalize(path);
57    let f = File::open(str.unwrap()).unwrap();
58    let file = BufReader::new(&f);
59    for (_num, line) in file.lines().enumerate() {
60      let l = line.unwrap();
61      let split: Vec<&str> = l.split_whitespace().collect();
62      let expected = hex::decode(split[0]).expect("Error parse expected");
63      let plain: Vec<u8>;
64      if split[1] == "x" {
65        plain = hex::decode("").expect("Error parse scalar");
66      } else {
67        plain = hex::decode(split[1]).expect("Error parse scalar");
68      }
69      let hash = Hash::fast(&plain);
70      assert!(hash == expected.as_slice());
71    }
72  }
73
74  #[test]
75
76  fn should_test_slow() {
77    let path = PathBuf::from("./tests/tests-slow.txt");
78    let str = canonicalize(path);
79    let f = File::open(str.unwrap()).unwrap();
80    let file = BufReader::new(&f);
81    for (_num, line) in file.lines().enumerate() {
82      let l = line.unwrap();
83      let split: Vec<&str> = l.split_whitespace().collect();
84      let expected = hex::decode(split[0]).expect("Error parse expected");
85      let plain: Vec<u8>;
86      if split[1] == "x" {
87        plain = hex::decode("").expect("Error parse scalar");
88      } else {
89        plain = hex::decode(split[1]).expect("Error parse scalar");
90      }
91      let hash = Hash::slow(&plain);
92      assert!(hash == expected.as_slice());
93    }
94  }
95
96  #[test]
97  fn should_get_fast_hash() {
98    let input = [
99      0x01, 0x3c, 0x01, 0xff, 0x00, 0x01, 0x01, 0x02, 0x9b, 0x2e, 0x4c, 0x02, 0x81, 0xc0, 0xb0,
100      0x2e, 0x7c, 0x53, 0x29, 0x1a, 0x94, 0xd1, 0xd0, 0xcb, 0xff, 0x88, 0x83, 0xf8, 0x02, 0x4f,
101      0x51, 0x42, 0xee, 0x49, 0x4f, 0xfb, 0xbd, 0x08, 0x80, 0x71, 0x21, 0x01, 0xa9, 0xa4, 0x56,
102      0x9f, 0x7e, 0x10, 0x16, 0x4a, 0x32, 0x32, 0x4b, 0x2b, 0x87, 0x8a, 0xe3, 0x2d, 0x98, 0xbe,
103      0x09, 0x49, 0xce, 0x6e, 0x01, 0x50, 0xba, 0x1d, 0x7e, 0x54, 0xd6, 0x09, 0x69, 0xe5,
104    ];
105    let hash = Hash::fast(&input);
106    assert!(
107      hash
108        == [
109          81, 131, 30, 137, 17, 68, 149, 122, 23, 4, 105, 195, 35, 123, 221, 255, 230, 192, 96, 73,
110          129, 38, 117, 210, 237, 178, 168, 52, 82, 247, 162, 80
111        ]
112    );
113
114    let input = [
115      50, 228, 229, 247, 39, 151, 194, 252, 14, 45, 218, 78, 128, 230, 27, 208, 9, 57, 52, 163, 5,
116      175, 8, 201, 211, 185, 66, 113, 88, 68, 170, 8,
117    ];
118    let hash = Hash::fast(&input);
119    assert!(
120      hash
121        == [
122          197, 173, 69, 56, 117, 95, 205, 188, 226, 116, 198, 205, 121, 235, 248, 74, 211, 46, 177,
123          65, 72, 147, 115, 194, 212, 214, 163, 109, 121, 3, 36, 249
124        ]
125    );
126    let input = [50];
127    let hash = Hash::fast(&input);
128    assert!(
129      hash
130        == [
131          173, 124, 91, 239, 2, 120, 22, 168, 0, 218, 23, 54, 68, 79, 181, 138, 128, 126, 244, 201,
132          96, 59, 120, 72, 103, 63, 126, 58, 104, 235, 20, 165
133        ]
134    );
135  }
136
137  #[test]
138  fn should_test_slow_hash() {
139    let path = PathBuf::from("./tests/hash/tests-slow.txt");
140    let str = canonicalize(path);
141    let f = File::open(str.unwrap()).unwrap();
142    let file = BufReader::new(&f);
143    for (_num, line) in file.lines().enumerate() {
144      let l = line.unwrap();
145      let split: Vec<&str> = l.split_whitespace().collect();
146      let expected = hex::decode(split[0]).expect("Error parse scalar");
147      let plain = hex::decode(split[1]).expect("Error parse scalar");
148      let actual = Hash::slow(&plain);
149      assert!(actual == expected.as_slice());
150    }
151  }
152}