1#![cfg_attr(not(feature = "std"), no_std)]
2
3use core::ffi::{c_char, c_int};
4use core::fmt;
5
6pub const TIDECOIN_HEADER_LEN: usize = 80;
8
9pub const TIDECOIN_HASH_LEN: usize = 32;
11
12unsafe extern "C" {
13 fn yespower_hash(input: *const c_char, output: *mut c_char) -> c_int;
14}
15
16#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
18pub struct Error;
19
20impl fmt::Display for Error {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 f.write_str("Tidecoin yespower hash failed")
23 }
24}
25
26#[cfg(feature = "std")]
27impl std::error::Error for Error {}
28
29pub fn tidecoin_hash(input: &[u8; TIDECOIN_HEADER_LEN]) -> Result<[u8; TIDECOIN_HASH_LEN], Error> {
34 let mut output = [0u8; TIDECOIN_HASH_LEN];
35 let result = unsafe {
39 yespower_hash(
40 input.as_ptr().cast::<c_char>(),
41 output.as_mut_ptr().cast::<c_char>(),
42 )
43 };
44
45 if result == 0 {
46 Ok(output)
47 } else {
48 Err(Error)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_hash() {
58 let input_hex = "0000002009f42768de3cfb4e58fc56368c1477f87f60e248d7130df3fb8acd7f6208b83a72f90dd3ad8fe06c7f70d73f256f1e07185dcc217a58b9517c699226ac0297d2ad60ba61b62a021d9b7700f0";
59 let expected_output_hex =
60 "9d90c21b5a0bb9566d2999c5d703d7327ee3ac97c020d387aa2dfd0700000000";
61
62 let input_bytes: [u8; 80] = hex::decode(input_hex)
63 .expect("Decoding failed")
64 .try_into()
65 .expect("Incorrect input length");
66 let expected_output_bytes: [u8; 32] = hex::decode(expected_output_hex)
67 .expect("Decoding failed")
68 .try_into()
69 .expect("Incorrect output length");
70
71 assert_eq!(tidecoin_hash(&input_bytes).unwrap(), expected_output_bytes);
72 }
73}