-
Notifications
You must be signed in to change notification settings - Fork 26
/
standard_miner.hpp
91 lines (75 loc) · 3.05 KB
/
standard_miner.hpp
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
//
// Standard miner. Relays and mines on longest chain it has seen.
//
#ifndef STANDARD_MINER_H
#define STANDARD_MINER_H
#include <boost/function.hpp>
#include <list>
#include <vector>
class Miner;
class PeerInfo {
public:
PeerInfo(Miner* _peer, int _chain_tip, double _latency) :
peer(_peer), chain_tip(_chain_tip), latency(_latency) { }
Miner* peer;
int chain_tip;
double latency;
};
class Miner
{
public:
// Return a random double in the range passed.
typedef boost::function<double(double, double)> JitterFunction;
Miner(double _hash_fraction, double _block_latency, JitterFunction _func) :
hash_fraction(_hash_fraction), block_latency(_block_latency), jitter_func(_func) {
best_chain = std::make_shared<std::vector<int>>();
}
void AddPeer(Miner* peer, double latency) {
peers.push_back(PeerInfo(peer, -1, latency));
}
virtual void FindBlock(CScheduler& s, int blockNumber) {
// Extend the chain:
auto chain_copy = std::make_shared<std::vector<int>>(best_chain->begin(), best_chain->end());
chain_copy->push_back(blockNumber);
best_chain = chain_copy;
#ifdef TRACE
std::cout << "Miner " << hash_fraction << " found block at simulation time " << s.getSimTime() << "\n";
#endif
RelayChain(this, s, chain_copy, block_latency);
}
virtual void ConsiderChain(Miner* from, CScheduler& s,
std::shared_ptr<std::vector<int>> chain, double latency) {
if (chain->size() > best_chain->size()) {
#ifdef TRACE
std::cout << "Miner " << hash_fraction << " relaying chain at simulation time " << s.getSimTime() << "\n";
#endif
best_chain = chain;
RelayChain(from, s, chain, latency);
}
}
virtual void RelayChain(Miner* from, CScheduler& s, std::shared_ptr<std::vector<int>> chain,
double latency) {
for (auto&& peer : peers) {
if (peer.chain_tip == chain->back()) continue; // Already relayed to this peer
peer.chain_tip = chain->back();
if (peer.peer == from) continue; // don't relay to peer that just sent it!
double jitter = 0;
if (peer.latency > 0) jitter = jitter_func(-peer.latency/1000., peer.latency/1000.);
double tPeer = s.getSimTime() + peer.latency + jitter + latency;
auto f = boost::bind(&Miner::ConsiderChain, peer.peer, from, boost::ref(s), chain, block_latency);
s.schedule(f, tPeer);
}
}
virtual void ResetChain() {
best_chain->clear();
}
const double GetHashFraction() const { return hash_fraction; }
std::vector<int> GetBestChain() const { return *best_chain; }
protected:
double hash_fraction; // This miner has hash_fraction of hash rate
double block_latency; // This miner produces blocks that take block_latency seconds to relay/validate
JitterFunction jitter_func;
std::shared_ptr<std::vector<int>> best_chain;
std::list<PeerInfo> peers;
};
#endif /* STANDARD_MINER_H */