/
digest32.rs
95 lines (84 loc) · 2.75 KB
/
digest32.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::chain::{Base16DecodedBytes, Base16EncodedBytes};
use blake2::digest::{Update, VariableOutput};
use blake2::VarBlake2b;
#[cfg(test)]
use proptest_derive::Arbitrary;
#[cfg(feature = "with-serde")]
use serde::{Deserialize, Serialize};
use sigma_ser::{
serializer::{SerializationError, SigmaSerializable},
vlq_encode,
};
use std::convert::TryFrom;
use std::convert::TryInto;
use std::io;
use thiserror::Error;
/// 32 byte array used in box, transaction ids (hash)
#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "with-serde",
serde(into = "Base16EncodedBytes", try_from = "Base16DecodedBytes")
)]
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct Digest32(pub Box<[u8; Digest32::SIZE]>);
impl Digest32 {
/// Digest size 32 bytes
pub const SIZE: usize = 32;
/// All zeros
pub fn zero() -> Digest32 {
Digest32(Box::new([0u8; Digest32::SIZE]))
}
}
/// Blake2b256 hash (256 bit)
pub fn blake2b256_hash(bytes: &[u8]) -> Digest32 {
// unwrap is safe 32 bytes is a valid hash size (<= 512 && 32 % 8 == 0)
let mut hasher = VarBlake2b::new(Digest32::SIZE).unwrap();
hasher.update(bytes);
let hash = hasher.finalize_boxed();
// unwrap is safe due to hash size is expected to be Digest32::SIZE
Digest32(hash.try_into().unwrap())
}
impl From<[u8; Digest32::SIZE]> for Digest32 {
fn from(bytes: [u8; Digest32::SIZE]) -> Self {
Digest32(Box::new(bytes))
}
}
impl Into<Base16EncodedBytes> for Digest32 {
fn into(self) -> Base16EncodedBytes {
Base16EncodedBytes::new(self.0.as_ref())
}
}
impl TryFrom<Base16DecodedBytes> for Digest32 {
type Error = Digest32Error;
fn try_from(bytes: Base16DecodedBytes) -> Result<Self, Self::Error> {
let arr: [u8; Digest32::SIZE] = bytes.0.as_slice().try_into()?;
Ok(Digest32(Box::new(arr)))
}
}
impl Into<String> for Digest32 {
fn into(self) -> String {
let bytes: Base16EncodedBytes = self.into();
bytes.into()
}
}
impl SigmaSerializable for Digest32 {
fn sigma_serialize<W: vlq_encode::WriteSigmaVlqExt>(&self, w: &mut W) -> Result<(), io::Error> {
w.write_all(self.0.as_ref())?;
Ok(())
}
fn sigma_parse<R: vlq_encode::ReadSigmaVlqExt>(r: &mut R) -> Result<Self, SerializationError> {
let mut bytes = [0; Digest32::SIZE];
r.read_exact(&mut bytes)?;
Ok(Self(bytes.into()))
}
}
/// Invalie byte array size
#[derive(Error, Debug)]
#[error("Invalid byte array size ({0})")]
pub struct Digest32Error(std::array::TryFromSliceError);
impl From<std::array::TryFromSliceError> for Digest32Error {
fn from(err: std::array::TryFromSliceError) -> Self {
Digest32Error(err)
}
}