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
112
113
114
115
116
117
118
119
120
use ethereum_types::{H256, U256};
use parking_lot::Mutex;
use std::{
collections::HashMap,
sync::Arc,
time::{Duration, Instant},
};
pub trait ExternalMinerService: Send + Sync {
fn submit_hashrate(&self, hashrate: U256, id: H256);
fn hashrate(&self) -> U256;
}
pub struct ExternalMiner {
hashrates: Arc<Mutex<HashMap<H256, (Instant, U256)>>>,
}
impl Default for ExternalMiner {
fn default() -> Self {
ExternalMiner {
hashrates: Arc::new(Mutex::new(HashMap::new())),
}
}
}
impl ExternalMiner {
pub fn new(hashrates: Arc<Mutex<HashMap<H256, (Instant, U256)>>>) -> Self {
ExternalMiner {
hashrates: hashrates,
}
}
}
const ENTRY_TIMEOUT: Duration = Duration::from_secs(2);
impl ExternalMinerService for ExternalMiner {
fn submit_hashrate(&self, hashrate: U256, id: H256) {
self.hashrates
.lock()
.insert(id, (Instant::now() + ENTRY_TIMEOUT, hashrate));
}
fn hashrate(&self) -> U256 {
let mut hashrates = self.hashrates.lock();
let h = hashrates
.drain()
.filter(|&(_, (t, _))| t > Instant::now())
.collect();
*hashrates = h;
hashrates
.iter()
.fold(U256::from(0), |sum, (_, &(_, v))| sum + v)
}
}
#[cfg(test)]
mod tests {
use super::*;
use ethereum_types::{H256, U256};
use std::{thread::sleep, time::Duration};
fn miner() -> ExternalMiner {
ExternalMiner::default()
}
#[test]
fn it_should_forget_old_hashrates() {
let m = miner();
assert_eq!(m.hashrate(), U256::from(0));
m.submit_hashrate(U256::from(10), H256::from_low_u64_be(1));
assert_eq!(m.hashrate(), U256::from(10));
sleep(Duration::from_secs(3));
assert_eq!(m.hashrate(), U256::from(0));
}
#[test]
fn should_sum_up_hashrate() {
let m = miner();
assert_eq!(m.hashrate(), U256::from(0));
m.submit_hashrate(U256::from(10), H256::from_low_u64_be(1));
assert_eq!(m.hashrate(), U256::from(10));
m.submit_hashrate(U256::from(15), H256::from_low_u64_be(1));
m.submit_hashrate(U256::from(20), H256::from_low_u64_be(2));
assert_eq!(m.hashrate(), U256::from(35));
}
}