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}