Newer
Older
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use serde::{Serialize, Deserialize};
use std::convert::TryInto;
#[cfg(any(test, test_utilities))]
use rand::Rng;
/// An object that can be meaningfully hashed.
pub trait Hashable {
/// Hash the object using SHA256.
fn hash(&self) -> H256;
}
/// A SHA256 hash.
#[derive(Eq, PartialEq, Serialize, Deserialize, Clone, Hash, Default, Copy)]
pub struct H256([u8; 32]); // big endian u256
impl Hashable for H256 {
fn hash(&self) -> H256 {
ring::digest::digest(&ring::digest::SHA256, &self.0).into()
}
}
impl std::fmt::Display for H256 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let start = if let Some(precision) = f.precision() {
if precision >= 64 {
0
} else {
32 - precision / 2
}
} else {
0
};
for byte_idx in start..32 {
write!(f, "{:>02x}", &self.0[byte_idx])?;
}
Ok(())
}
}
impl std::fmt::Debug for H256 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{:>02x}{:>02x}..{:>02x}{:>02x}",
&self.0[0], &self.0[1], &self.0[30], &self.0[31]
)
}
}
impl std::convert::AsRef<[u8]> for H256 {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl std::convert::From<&[u8; 32]> for H256 {
fn from(input: &[u8; 32]) -> H256 {
let mut buffer: [u8; 32] = [0; 32];
buffer[..].copy_from_slice(input);
H256(buffer)
}
}
impl std::convert::From<&H256> for [u8; 32] {
fn from(input: &H256) -> [u8; 32] {
let mut buffer: [u8; 32] = [0; 32];
buffer[..].copy_from_slice(&input.0);
buffer
}
}
impl std::convert::From<[u8; 32]> for H256 {
fn from(input: [u8; 32]) -> H256 {
H256(input)
}
}
impl std::convert::From<H256> for [u8; 32] {
fn from(input: H256) -> [u8; 32] {
input.0
}
}
impl std::convert::From<ring::digest::Digest> for H256 {
fn from(input: ring::digest::Digest) -> H256 {
let mut raw_hash: [u8; 32] = [0; 32];
raw_hash[0..32].copy_from_slice(input.as_ref());
H256(raw_hash)
}
}
impl Ord for H256 {
fn cmp(&self, other: &H256) -> std::cmp::Ordering {
let self_higher = u128::from_be_bytes(self.0[0..16].try_into().unwrap());
let self_lower = u128::from_be_bytes(self.0[16..32].try_into().unwrap());
let other_higher = u128::from_be_bytes(other.0[0..16].try_into().unwrap());
let other_lower = u128::from_be_bytes(other.0[16..32].try_into().unwrap());
let higher = self_higher.cmp(&other_higher);
match higher {
std::cmp::Ordering::Equal => self_lower.cmp(&other_lower),
_ => higher,
}
}
}
impl PartialOrd for H256 {
fn partial_cmp(&self, other: &H256) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
pub fn random_hash() -> H256 {
let mut rng = rand::thread_rng();
let random_bytes: Vec<u8> = (0..32).map(|_| rand::random()).collect();
let mut raw_bytes = [0; 32];
raw_bytes.copy_from_slice(&random_bytes);
(&raw_bytes).into()
}
#[cfg(any(test, test_utilities))]
pub fn generate_random_hash() -> H256 {
let mut rng = rand::thread_rng();
let random_bytes: Vec<u8> = (0..32).map(|_| rng.gen()).collect();
let mut raw_bytes = [0; 32];
raw_bytes.copy_from_slice(&random_bytes);
(&raw_bytes).into()