1use std::hash::{Hash, Hasher};
5use std::io::{BufRead, Write};
6use std::str::FromStr;
7use std::{error, fmt, result};
8
9use cbor_event::{self, de::Deserializer, se::Serializer};
10use cryptoxide::blake2b::Blake2b;
11use cryptoxide::digest::Digest as _;
12use cryptoxide::sha3;
13use hex::FromHexError;
14
15use crate::chain_crypto::bech32::{self, Bech32};
16
17#[derive(Debug, PartialEq, Clone)]
18pub enum Error {
19 InvalidHashSize(usize, usize),
20 InvalidHexEncoding(FromHexError),
21}
22impl fmt::Display for Error {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 match self {
25 Error::InvalidHashSize(sz, expected) => write!(
26 f,
27 "invalid hash size, expected {expected} but received {sz} bytes."
28 ),
29 Error::InvalidHexEncoding(_) => write!(f, "invalid hex encoding for hash value"),
30 }
31 }
32}
33impl error::Error for Error {
34 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
35 match self {
36 Error::InvalidHashSize(..) => None,
37 Error::InvalidHexEncoding(err) => Some(err),
38 }
39 }
40}
41
42impl From<FromHexError> for Error {
43 fn from(err: FromHexError) -> Self {
44 Error::InvalidHexEncoding(err)
45 }
46}
47
48pub type Result<T> = result::Result<T, Error>;
49
50macro_rules! define_blake2b_new {
52 ($hash_ty:ty) => {
53 impl $hash_ty {
54 pub fn new(buf: &[u8]) -> Self {
55 let mut b2b = Blake2b::new(Self::HASH_SIZE);
56 let mut out = [0; Self::HASH_SIZE];
57 b2b.input(buf);
58 b2b.result(&mut out);
59 Self::from(out)
60 }
61 }
62 };
63}
64macro_rules! define_hash_object {
65 ($hash_ty:ty, $constructor:expr, $hash_size:ident, $bech32_hrp:expr) => {
66 impl $hash_ty {
67 pub const HASH_SIZE: usize = $hash_size;
68
69 pub fn as_hash_bytes(&self) -> &[u8; Self::HASH_SIZE] {
70 &self.0
71 }
72
73 pub fn try_from_slice(slice: &[u8]) -> Result<Self> {
74 if slice.len() != Self::HASH_SIZE {
75 return Err(Error::InvalidHashSize(slice.len(), Self::HASH_SIZE));
76 }
77 let mut buf = [0; Self::HASH_SIZE];
78
79 buf[0..Self::HASH_SIZE].clone_from_slice(slice);
80 Ok(Self::from(buf))
81 }
82 }
83 impl AsRef<[u8]> for $hash_ty {
84 fn as_ref(&self) -> &[u8] {
85 self.0.as_ref()
86 }
87 }
88 impl From<$hash_ty> for [u8; $hash_size] {
89 fn from(bytes: $hash_ty) -> Self {
90 bytes.0
91 }
92 }
93 impl<'a> From<&'a $hash_ty> for &'a [u8; $hash_size] {
94 fn from(bytes: &'a $hash_ty) -> Self {
95 &bytes.0
96 }
97 }
98 impl From<[u8; Self::HASH_SIZE]> for $hash_ty {
99 fn from(bytes: [u8; Self::HASH_SIZE]) -> Self {
100 $constructor(bytes)
101 }
102 }
103 #[allow(clippy::derived_hash_with_manual_eq)]
105 impl Hash for $hash_ty {
106 fn hash<H: Hasher>(&self, state: &mut H) {
107 self.0.hash(state)
108 }
109 }
110 impl FromStr for $hash_ty {
111 type Err = Error;
112 fn from_str(s: &str) -> result::Result<Self, Self::Err> {
113 let bytes = hex::decode(s)?;
114 Self::try_from_slice(&bytes)
115 }
116 }
117 impl fmt::Display for $hash_ty {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 write!(f, "{}", hex::encode(self.as_ref()))
120 }
121 }
122 impl fmt::Debug for $hash_ty {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 f.write_str(concat!(stringify!($hash_ty), "(0x"))?;
125 write!(f, "{}", hex::encode(self.as_ref()))?;
126 f.write_str(")")
127 }
128 }
129 impl Bech32 for $hash_ty {
130 const BECH32_HRP: &'static str = $bech32_hrp;
131
132 fn try_from_bech32_str(bech32_str: &str) -> bech32::Result<Self> {
133 let bytes = bech32::try_from_bech32_to_bytes::<Self>(bech32_str)?;
134 Self::try_from_slice(&bytes).map_err(bech32::Error::data_invalid)
135 }
136
137 fn to_bech32_str(&self) -> String {
138 bech32::to_bech32_from_bytes::<Self>(self.as_ref())
139 }
140 }
141 impl cbor_event::de::Deserialize for $hash_ty {
142 fn deserialize<R: BufRead>(reader: &mut Deserializer<R>) -> cbor_event::Result<Self> {
143 let bytes = reader.bytes()?;
144 match Self::try_from_slice(&bytes) {
145 Ok(digest) => Ok(digest),
146 Err(Error::InvalidHashSize(sz, expected)) => {
147 Err(cbor_event::Error::NotEnough(sz, expected))
148 }
149 Err(err) => Err(cbor_event::Error::CustomError(format!(
150 "unexpected error: {:?}",
151 err
152 ))),
153 }
154 }
155 }
156 impl cbor_event::se::Serialize for $hash_ty {
157 fn serialize<'se, W: Write>(
158 &self,
159 serializer: &'se mut Serializer<W>,
160 ) -> cbor_event::Result<&'se mut Serializer<W>> {
161 serializer.write_bytes(self.as_ref())
162 }
163 }
164
165 #[cfg(feature = "generic-serialization")]
166 impl serde::Serialize for $hash_ty {
167 #[inline]
168 fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
169 where
170 S: serde::Serializer,
171 {
172 if serializer.is_human_readable() {
173 serializer.serialize_str(&hex::encode(self.as_ref()))
174 } else {
175 serializer.serialize_bytes(&self.as_ref())
176 }
177 }
178 }
179 #[cfg(feature = "generic-serialization")]
180 impl<'de> serde::Deserialize<'de> for $hash_ty {
181 fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
182 where
183 D: serde::Deserializer<'de>,
184 {
185 struct HashVisitor;
186 impl<'de> serde::de::Visitor<'de> for HashVisitor {
187 type Value = $hash_ty;
188
189 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
190 write!(fmt, "Expecting a Blake2b_256 hash (`Hash`)")
191 }
192
193 fn visit_str<'a, E>(self, v: &'a str) -> result::Result<Self::Value, E>
194 where
195 E: serde::de::Error,
196 {
197 match Self::Value::from_str(&v) {
198 Err(Error::HexadecimalError(err)) => Err(E::custom(format!("{}", err))),
199 Err(Error::InvalidHashSize(sz, _)) => {
200 Err(E::invalid_length(sz, &"32 bytes"))
201 }
202 Ok(h) => Ok(h),
203 }
204 }
205
206 fn visit_bytes<'a, E>(self, v: &'a [u8]) -> result::Result<Self::Value, E>
207 where
208 E: serde::de::Error,
209 {
210 match Self::Value::try_from_slice(v) {
211 Err(Error::InvalidHashSize(sz, _)) => {
212 Err(E::invalid_length(sz, &"32 bytes"))
213 }
214 Err(err) => panic!("unexpected error: {}", err),
215 Ok(h) => Ok(h),
216 }
217 }
218 }
219
220 if deserializer.is_human_readable() {
221 deserializer.deserialize_str(HashVisitor)
222 } else {
223 deserializer.deserialize_bytes(HashVisitor)
224 }
225 }
226 }
227 };
228}
229
230pub const HASH_SIZE_224: usize = 28;
231pub const HASH_SIZE_256: usize = 32;
232
233#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
235pub struct Blake2b256([u8; HASH_SIZE_256]);
236define_hash_object!(Blake2b256, Blake2b256, HASH_SIZE_256, "blake2b256");
237define_blake2b_new!(Blake2b256);
238
239#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
241pub struct Blake2b224([u8; HASH_SIZE_224]);
242define_hash_object!(Blake2b224, Blake2b224, HASH_SIZE_224, "blake2b224");
243define_blake2b_new!(Blake2b224);
244
245#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
246pub struct Sha3_256([u8; HASH_SIZE_256]);
247define_hash_object!(Sha3_256, Sha3_256, HASH_SIZE_256, "sha3256");
248impl Sha3_256 {
249 pub fn new(buf: &[u8]) -> Self {
250 let mut sh3 = sha3::Sha3_256::new();
251 let mut out = [0; Self::HASH_SIZE];
252 sh3.input(buf.as_ref());
253 sh3.result(&mut out);
254 Self::from(out)
255 }
256}