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
use super::address::CryptoAddress;
use crate::prelude::*;
use blake3::Hasher;
use ibig::UBig;
use lazy_static::lazy_static;
use num_traits::identities::One;
use std::default::Default;
lazy_static! {
static ref P: UBig = "50763434429823703141085322590076158163032399096130816327134180611270739679038131809123861970975131471260684737408234060876742190838745219274061025048845231234136148410311444604554192918702297959809128216170781389312847013812749872750274650041183009144583521632294518996531883338553737214586176414455965584933129379474747808392433032576309945590584603359054260866543918929486383805924215982747035136255123252119828736134723149397165643360162699752374292974151421555939481822911026769138419707577501643119472226283015793622652706604535623136902831581637275314074553942039263472515423713366344495524733341031029964603383".parse().unwrap();
}
pub struct CryptoStableHasher {
value: UBig,
}
impl Default for CryptoStableHasher {
fn default() -> Self {
Self { value: UBig::one() }
}
}
impl CryptoStableHasher {
#[inline]
fn mixin_raw(&mut self, digits: &UBig) {
profile_method!(mixin_raw);
self.value *= digits;
self.value %= &*P;
}
}
impl StableHasher for CryptoStableHasher {
type Out = [u8; 32];
type Addr = CryptoAddress;
type Bytes = Vec<u8>;
#[inline]
fn new() -> Self {
profile_method!(new);
Default::default()
}
fn write(&mut self, field_address: Self::Addr, bytes: &[u8]) {
profile_method!(write);
let mut output = field_address.finish(bytes);
let mut digits = [0u8; 256];
output.fill(&mut digits);
let digits = UBig::from_le_bytes(&digits);
self.mixin_raw(&digits)
}
fn mixin(&mut self, other: &Self) {
profile_method!(mixin);
self.mixin_raw(&other.value)
}
fn finish(&self) -> Self::Out {
profile_method!(finish);
let mut hasher = Hasher::new();
let le = self.value.to_le_bytes();
hasher.update(&le);
hasher.finalize().into()
}
fn to_bytes(&self) -> Self::Bytes {
profile_method!(to_bytes);
self.value.to_le_bytes()
}
fn from_bytes(bytes: Vec<u8>) -> Self {
profile_method!(from_bytes);
assert!(bytes.len() <= 257);
let value = UBig::from_le_bytes(&bytes);
Self { value }
}
}