use crate::hash::sha256;
use crate::PrimitivesError;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::str::FromStr;
pub const HASH_SIZE: usize = 32;
pub const MAX_HASH_STRING_SIZE: usize = HASH_SIZE * 2;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
pub struct Hash([u8; HASH_SIZE]);
impl Hash {
pub fn new(bytes: [u8; HASH_SIZE]) -> Self {
Hash(bytes)
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, PrimitivesError> {
if bytes.len() != HASH_SIZE {
return Err(PrimitivesError::InvalidHash(format!(
"invalid hash length of {}, want {}",
bytes.len(),
HASH_SIZE
)));
}
let mut arr = [0u8; HASH_SIZE];
arr.copy_from_slice(bytes);
Ok(Hash(arr))
}
pub fn from_hex(hex_str: &str) -> Result<Self, PrimitivesError> {
if hex_str.is_empty() {
return Ok(Hash::default());
}
if hex_str.len() > MAX_HASH_STRING_SIZE {
return Err(PrimitivesError::InvalidHash(format!(
"max hash string length is {} bytes",
MAX_HASH_STRING_SIZE
)));
}
let padded = if !hex_str.len().is_multiple_of(2) {
format!("0{}", hex_str)
} else {
hex_str.to_string()
};
let decoded = hex::decode(&padded)?;
let mut reversed_hash = [0u8; HASH_SIZE];
let offset = HASH_SIZE - decoded.len();
reversed_hash[offset..].copy_from_slice(&decoded);
let mut dst = [0u8; HASH_SIZE];
for i in 0..HASH_SIZE {
dst[i] = reversed_hash[HASH_SIZE - 1 - i];
}
Ok(Hash(dst))
}
pub fn clone_bytes(&self) -> Vec<u8> {
self.0.to_vec()
}
pub fn set_bytes(&mut self, bytes: &[u8]) -> Result<(), PrimitivesError> {
if bytes.len() != HASH_SIZE {
return Err(PrimitivesError::InvalidHash(format!(
"invalid hash length of {}, want {}",
bytes.len(),
HASH_SIZE
)));
}
self.0.copy_from_slice(bytes);
Ok(())
}
pub fn is_equal(&self, other: Option<&Hash>) -> bool {
match other {
Some(h) => self.0 == h.0,
None => false,
}
}
pub fn as_bytes(&self) -> &[u8; HASH_SIZE] {
&self.0
}
pub fn size(&self) -> usize {
HASH_SIZE
}
}
impl fmt::Display for Hash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut reversed = self.0;
reversed.reverse();
write!(f, "{}", hex::encode(reversed))
}
}
impl FromStr for Hash {
type Err = PrimitivesError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Hash::from_hex(s)
}
}
impl Serialize for Hash {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for Hash {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
Hash::from_hex(&s).map_err(serde::de::Error::custom)
}
}
pub fn hash_h(data: &[u8]) -> Hash {
Hash(sha256(data))
}
pub fn double_hash_h(data: &[u8]) -> Hash {
Hash(crate::hash::sha256d(data))
}
#[cfg(test)]
mod tests {
use super::*;
const MAIN_NET_GENESIS_HASH: Hash = Hash([
0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7,
0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00,
0x00, 0x00,
]);
#[test]
fn test_hash_api() {
let block_hash_str = "14a0810ac680a3eb3f82edc878cea25ec41d6b790744e5daeef";
let block_hash = Hash::from_hex(block_hash_str).unwrap();
let buf: [u8; 32] = [
0x79, 0xa6, 0x1a, 0xdb, 0xc6, 0xe5, 0xa2, 0xe1, 0x39, 0xd2, 0x71, 0x3a, 0x54, 0x6e,
0xc7, 0xc8, 0x75, 0x63, 0x2e, 0x75, 0xf1, 0xdf, 0x9c, 0x3f, 0xa6, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let hash = Hash::from_bytes(&buf).unwrap();
assert_eq!(hash.size(), HASH_SIZE);
assert_eq!(hash.as_bytes(), &buf);
assert!(!hash.is_equal(Some(&block_hash)));
let mut hash2 = hash;
hash2.set_bytes(&block_hash.clone_bytes()).unwrap();
assert!(hash2.is_equal(Some(&block_hash)));
assert!(!hash.is_equal(None));
let mut h = Hash::default();
assert!(h.set_bytes(&[0x00]).is_err());
let invalid = vec![0u8; HASH_SIZE + 1];
assert!(Hash::from_bytes(&invalid).is_err());
}
#[test]
fn test_hash_string() {
let hash = Hash::new([
0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39, 0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04,
0xb0, 0xd2, 0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa, 0x27, 0xba, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00,
]);
assert_eq!(
hash.to_string(),
"000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
);
}
#[test]
fn test_new_hash_from_hex() {
let result =
Hash::from_hex("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
.unwrap();
assert_eq!(result, MAIN_NET_GENESIS_HASH);
let result =
Hash::from_hex("19d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap();
assert_eq!(result, MAIN_NET_GENESIS_HASH);
let result = Hash::from_hex("").unwrap();
assert_eq!(result, Hash::default());
let result = Hash::from_hex("1").unwrap();
let expected = Hash::new([
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]);
assert_eq!(result, expected);
let result = Hash::from_hex("3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc").unwrap();
let expected = Hash::new([
0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7, 0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4,
0xa1, 0x0b, 0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b, 0x26, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
]);
assert_eq!(result, expected);
let result =
Hash::from_hex("01234567890123456789012345678901234567890123456789012345678912345");
assert!(result.is_err());
let result = Hash::from_hex("abcdefg");
assert!(result.is_err());
}
#[test]
fn test_marshalling() {
#[derive(Serialize, Deserialize)]
struct TestData {
hash: Hash,
}
let data = TestData {
hash: hash_h(b"hello"),
};
assert_eq!(
data.hash.to_string(),
"24988b93623304735e42a71f5c1e161b9ee2b9c52a3be8260ea3b05fba4df22c"
);
let json = serde_json::to_string(&data).unwrap();
assert_eq!(
json,
r#"{"hash":"24988b93623304735e42a71f5c1e161b9ee2b9c52a3be8260ea3b05fba4df22c"}"#
);
let data2: TestData = serde_json::from_str(&json).unwrap();
assert_eq!(
data2.hash.to_string(),
"24988b93623304735e42a71f5c1e161b9ee2b9c52a3be8260ea3b05fba4df22c"
);
}
}