use crate::ser::{self, Error, ProtocolVersion, Readable, Reader, Writeable, Writer};
use blake2::blake2b::Blake2b;
use byteorder::{BigEndian, ByteOrder};
use std::{cmp::min, convert::AsRef, fmt, ops};
use util::ToHex;
pub const ZERO_HASH: Hash = Hash([0; 32]);
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub struct Hash([u8; 32]);
impl DefaultHashable for Hash {}
impl fmt::Debug for Hash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let hash_hex = self.to_hex();
const NUM_SHOW: usize = 12;
write!(f, "{}", &hash_hex[..NUM_SHOW])
}
}
impl fmt::Display for Hash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl Hash {
pub const LEN: usize = 32;
pub fn from_vec(v: &[u8]) -> Hash {
let mut h = [0; Hash::LEN];
let copy_size = min(v.len(), Hash::LEN);
h[..copy_size].copy_from_slice(&v[..copy_size]);
Hash(h)
}
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
pub fn from_hex(hex: &str) -> Result<Hash, Error> {
let bytes = util::from_hex(hex)
.map_err(|_| Error::HexError(format!("failed to decode {}", hex)))?;
Ok(Hash::from_vec(&bytes))
}
pub fn to_u64(&self) -> u64 {
BigEndian::read_u64(&self.0)
}
}
impl ops::Index<usize> for Hash {
type Output = u8;
fn index(&self, idx: usize) -> &u8 {
&self.0[idx]
}
}
impl ops::Index<ops::Range<usize>> for Hash {
type Output = [u8];
fn index(&self, idx: ops::Range<usize>) -> &[u8] {
&self.0[idx]
}
}
impl ops::Index<ops::RangeTo<usize>> for Hash {
type Output = [u8];
fn index(&self, idx: ops::RangeTo<usize>) -> &[u8] {
&self.0[idx]
}
}
impl ops::Index<ops::RangeFrom<usize>> for Hash {
type Output = [u8];
fn index(&self, idx: ops::RangeFrom<usize>) -> &[u8] {
&self.0[idx]
}
}
impl ops::Index<ops::RangeFull> for Hash {
type Output = [u8];
fn index(&self, idx: ops::RangeFull) -> &[u8] {
&self.0[idx]
}
}
impl AsRef<[u8]> for Hash {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl Readable for Hash {
fn read<R: Reader>(reader: &mut R) -> Result<Hash, ser::Error> {
let v = reader.read_fixed_bytes(32)?;
let mut a = [0; 32];
a.copy_from_slice(&v[..]);
Ok(Hash(a))
}
}
impl Writeable for Hash {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
writer.write_fixed_bytes(&self.0)
}
}
impl Default for Hash {
fn default() -> Hash {
ZERO_HASH
}
}
pub struct HashWriter {
state: Blake2b,
}
impl HashWriter {
pub fn finalize(self, output: &mut [u8]) {
output.copy_from_slice(self.state.finalize().as_bytes());
}
pub fn into_hash(self) -> Hash {
let mut res = [0; 32];
res.copy_from_slice(self.state.finalize().as_bytes());
Hash(res)
}
}
impl Default for HashWriter {
fn default() -> HashWriter {
HashWriter {
state: Blake2b::new(32),
}
}
}
impl ser::Writer for HashWriter {
fn serialization_mode(&self) -> ser::SerializationMode {
ser::SerializationMode::Hash
}
fn write_fixed_bytes<T: AsRef<[u8]>>(&mut self, bytes: T) -> Result<(), ser::Error> {
self.state.update(bytes.as_ref());
Ok(())
}
fn protocol_version(&self) -> ProtocolVersion {
ProtocolVersion::local()
}
}
pub trait Hashed {
fn hash(&self) -> Hash;
}
pub trait DefaultHashable: Writeable {}
impl<D: DefaultHashable> Hashed for D {
fn hash(&self) -> Hash {
let mut hasher = HashWriter::default();
Writeable::write(self, &mut hasher).unwrap();
let mut ret = [0; 32];
hasher.finalize(&mut ret);
Hash(ret)
}
}
impl<D: DefaultHashable> DefaultHashable for &D {}
impl<D: DefaultHashable, E: DefaultHashable> DefaultHashable for (D, E) {}
impl<D: DefaultHashable, E: DefaultHashable, F: DefaultHashable> DefaultHashable for (D, E, F) {}
impl DefaultHashable for util::secp::pedersen::RangeProof {}
impl DefaultHashable for Vec<u8> {}
impl DefaultHashable for u8 {}
impl DefaultHashable for u64 {}