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
use keccak::{keccak_256, H256};
use shared;
use std::cell::Cell;
#[derive(Default)]
pub struct SeedHashCompute {
prev_epoch: Cell<u64>,
prev_seedhash: Cell<H256>,
}
impl SeedHashCompute {
#[inline]
fn reset_cache(&self) {
self.prev_epoch.set(0);
self.prev_seedhash.set([0u8; 32]);
}
#[inline]
pub fn hash_block_number(&self, block_number: u64) -> H256 {
self.hash_epoch(shared::epoch(block_number))
}
#[inline]
pub fn hash_epoch(&self, epoch: u64) -> H256 {
if epoch < self.prev_epoch.get() {
self.reset_cache();
}
if epoch > self.prev_epoch.get() {
let seed_hash = SeedHashCompute::resume_compute_seedhash(
self.prev_seedhash.get(),
self.prev_epoch.get(),
epoch,
);
self.prev_seedhash.set(seed_hash);
self.prev_epoch.set(epoch);
}
self.prev_seedhash.get()
}
#[inline]
pub fn resume_compute_seedhash(mut hash: H256, start_epoch: u64, end_epoch: u64) -> H256 {
for _ in start_epoch..end_epoch {
keccak_256::inplace(&mut hash);
}
hash
}
}
#[cfg(test)]
mod tests {
use super::SeedHashCompute;
#[test]
fn test_seed_compute_once() {
let seed_compute = SeedHashCompute::default();
let hash = [
241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253,
147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162,
];
assert_eq!(seed_compute.hash_block_number(486382), hash);
}
#[test]
fn test_seed_compute_zero() {
let seed_compute = SeedHashCompute::default();
assert_eq!(seed_compute.hash_block_number(0), [0u8; 32]);
}
#[test]
fn test_seed_compute_after_older() {
let seed_compute = SeedHashCompute::default();
let _ = seed_compute.hash_block_number(50000);
let hash = [
241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253,
147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162,
];
assert_eq!(seed_compute.hash_block_number(486382), hash);
}
#[test]
fn test_seed_compute_after_newer() {
let seed_compute = SeedHashCompute::default();
let _ = seed_compute.hash_block_number(972764);
let hash = [
241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253,
147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162,
];
assert_eq!(seed_compute.hash_block_number(486382), hash);
}
}