Bitcoin ABC  0.24.11
P2P Digital Currency
peermanager.h
Go to the documentation of this file.
1 // Copyright (c) 2020 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef BITCOIN_AVALANCHE_PEERMANAGER_H
6 #define BITCOIN_AVALANCHE_PEERMANAGER_H
7 
8 #include <avalanche/node.h>
9 #include <avalanche/proof.h>
10 #include <avalanche/proofpool.h>
11 #include <coins.h>
12 #include <pubkey.h>
13 #include <salteduint256hasher.h>
14 #include <util/time.h>
15 
16 #include <boost/multi_index/composite_key.hpp>
17 #include <boost/multi_index/hashed_index.hpp>
18 #include <boost/multi_index/mem_fun.hpp>
19 #include <boost/multi_index/member.hpp>
20 #include <boost/multi_index/ordered_index.hpp>
21 #include <boost/multi_index_container.hpp>
22 
23 #include <chrono>
24 #include <cstdint>
25 #include <memory>
26 #include <unordered_set>
27 #include <vector>
28 
29 namespace avalanche {
30 
31 class Delegation;
32 
33 namespace {
34  struct TestPeerManager;
35 }
36 
37 struct Slot {
38 private:
39  uint64_t start;
40  uint32_t score;
42 
43 public:
44  Slot(uint64_t startIn, uint32_t scoreIn, PeerId peeridIn)
45  : start(startIn), score(scoreIn), peerid(peeridIn) {}
46 
47  Slot withStart(uint64_t startIn) const {
48  return Slot(startIn, score, peerid);
49  }
50  Slot withScore(uint64_t scoreIn) const {
51  return Slot(start, scoreIn, peerid);
52  }
53  Slot withPeerId(PeerId peeridIn) const {
54  return Slot(start, score, peeridIn);
55  }
56 
57  uint64_t getStart() const { return start; }
58  uint64_t getStop() const { return start + score; }
59  uint32_t getScore() const { return score; }
60  PeerId getPeerId() const { return peerid; }
61 
62  bool contains(uint64_t slot) const {
63  return getStart() <= slot && slot < getStop();
64  }
65  bool precedes(uint64_t slot) const { return slot >= getStop(); }
66  bool follows(uint64_t slot) const { return getStart() > slot; }
67 };
68 
69 struct Peer {
71  uint32_t index = -1;
72  uint32_t node_count = 0;
73 
75 
76  // The network stack uses timestamp in seconds, so we oblige.
77  std::chrono::seconds registration_time;
78  std::chrono::seconds nextPossibleConflictTime;
79 
80  Peer(PeerId peerid_, ProofRef proof_)
81  : peerid(peerid_), proof(std::move(proof_)),
82  registration_time(GetTime<std::chrono::seconds>()),
84 
85  const ProofId &getProofId() const { return proof->getId(); }
86  uint32_t getScore() const { return proof->getScore(); }
87 };
88 
89 struct proof_index {
91  result_type operator()(const Peer &p) const { return p.proof->getId(); }
92 };
93 
95 
96 struct PendingNode {
99 
100  PendingNode(ProofId proofid_, NodeId nodeid_)
101  : proofid(proofid_), nodeid(nodeid_){};
102 };
103 
104 struct by_proofid;
105 struct by_nodeid;
106 
107 namespace bmi = boost::multi_index;
108 
109 class PeerManager {
110  std::vector<Slot> slots;
111  uint64_t slotCount = 0;
112  uint64_t fragmentation = 0;
113 
118  using PeerSet = boost::multi_index_container<
119  Peer, bmi::indexed_by<
120  // index by peerid
121  bmi::hashed_unique<bmi::member<Peer, PeerId, &Peer::peerid>>,
122  // index by proof
123  bmi::hashed_unique<bmi::tag<by_proofid>, proof_index,
125 
128 
132 
133  using NodeSet = boost::multi_index_container<
134  Node,
135  bmi::indexed_by<
136  // index by nodeid
137  bmi::hashed_unique<bmi::member<Node, NodeId, &Node::nodeid>>,
138  // sorted by peerid/nextRequestTime
139  bmi::ordered_non_unique<
140  bmi::tag<next_request_time>,
141  bmi::composite_key<
142  Node, bmi::member<Node, PeerId, &Node::peerid>,
143  bmi::member<Node, TimePoint, &Node::nextRequestTime>>>>>;
144 
146 
147  using PendingNodeSet = boost::multi_index_container<
148  PendingNode,
149  bmi::indexed_by<
150  // index by proofid
151  bmi::hashed_non_unique<
152  bmi::tag<by_proofid>,
153  bmi::member<PendingNode, ProofId, &PendingNode::proofid>,
155  // index by nodeid
156  bmi::hashed_unique<
157  bmi::tag<by_nodeid>,
158  bmi::member<PendingNode, NodeId, &PendingNode::nodeid>>>>;
160 
161  static constexpr int SELECT_PEER_MAX_RETRY = 3;
162  static constexpr int SELECT_NODE_MAX_RETRY = 3;
163 
167  std::unordered_set<ProofId, SaltedProofIdHasher> m_unbroadcast_proofids;
168 
169 public:
173  bool addNode(NodeId nodeid, const ProofId &proofid);
174  bool removeNode(NodeId nodeid);
175 
176  // Update when a node is to be polled next.
177  bool updateNextRequestTime(NodeId nodeid, TimePoint timeout);
178 
179  // Randomly select a node to poll.
180  NodeId selectNode();
181 
182  template <typename Callable>
183  bool forNode(NodeId nodeid, Callable &&func) const {
184  auto it = nodes.find(nodeid);
185  return it != nodes.end() && func(*it);
186  }
187 
188  template <typename Callable>
189  void forEachNode(const Peer &peer, Callable &&func) const {
190  auto &nview = nodes.get<next_request_time>();
191  auto range = nview.equal_range(peer.peerid);
192  for (auto it = range.first; it != range.second; ++it) {
193  func(*it);
194  }
195  }
196 
206  const std::chrono::seconds &nextTime);
207 
215  enum class RegistrationMode {
216  DEFAULT,
217  FORCE_ACCEPT,
218  };
219 
220  bool registerProof(const ProofRef &proof,
222  bool exists(const ProofId &proofid) const {
223  return getProof(proofid) != nullptr;
224  }
225 
226  template <typename Callable>
227  bool forPeer(const ProofId &proofid, Callable &&func) const {
228  auto &pview = peers.get<by_proofid>();
229  auto it = pview.find(proofid);
230  return it != pview.end() && func(*it);
231  }
232 
233  template <typename Callable> void forEachPeer(Callable &&func) const {
234  for (const auto &p : peers) {
235  func(p);
236  }
237  }
238 
242  void updatedBlockTip();
243 
247  void addUnbroadcastProof(const ProofId &proofid);
248  void removeUnbroadcastProof(const ProofId &proofid);
250 
251  /****************************************************
252  * Functions which are public for testing purposes. *
253  ****************************************************/
254 
258  bool removePeer(const PeerId peerid);
259 
263  PeerId selectPeer() const;
264 
269  uint64_t compact();
270 
274  bool verify() const;
275 
276  // Accessors.
277  uint64_t getSlotCount() const { return slotCount; }
278  uint64_t getFragmentation() const { return fragmentation; }
279 
280  ProofRef getProof(const ProofId &proofid) const;
281  bool isBoundToPeer(const ProofId &proofid) const;
282  bool isOrphan(const ProofId &proofid) const;
283  bool isInConflictingPool(const ProofId &proofid) const;
284 
285 private:
286  bool addOrUpdateNode(const PeerSet::iterator &it, NodeId nodeid);
287  bool addNodeToPeer(const PeerSet::iterator &it);
288  bool removeNodeFromPeer(const PeerSet::iterator &it, uint32_t count = 1);
289 
290  friend struct ::avalanche::TestPeerManager;
291 };
292 
296 PeerId selectPeerImpl(const std::vector<Slot> &slots, const uint64_t slot,
297  const uint64_t max);
298 
299 } // namespace avalanche
300 
301 #endif // BITCOIN_AVALANCHE_PEERMANAGER_H
avalanche::PeerManager::verify
bool verify() const
Perform consistency check on internal data structures.
Definition: peermanager.cpp:451
avalanche::PendingNode::nodeid
NodeId nodeid
Definition: peermanager.h:98
avalanche::Slot
Definition: peermanager.h:37
avalanche::Slot::withPeerId
Slot withPeerId(PeerId peeridIn) const
Definition: peermanager.h:53
avalanche::PeerManager::forNode
bool forNode(NodeId nodeid, Callable &&func) const
Definition: peermanager.h:183
avalanche::PeerManager::SELECT_PEER_MAX_RETRY
static constexpr int SELECT_PEER_MAX_RETRY
Definition: peermanager.h:161
count
static int count
Definition: tests.c:41
avalanche::PeerManager::nodes
NodeSet nodes
Definition: peermanager.h:145
avalanche::PeerManager::updateNextRequestTime
bool updateNextRequestTime(NodeId nodeid, TimePoint timeout)
Definition: peermanager.cpp:136
avalanche::Peer::Peer
Peer(PeerId peerid_, ProofRef proof_)
Definition: peermanager.h:80
avalanche::PeerManager::compact
uint64_t compact()
Trigger maintenance of internal data structures.
Definition: peermanager.cpp:419
avalanche::PeerManager::nextPeerId
PeerId nextPeerId
Definition: peermanager.h:126
avalanche::SaltedProofIdHasher
Definition: proofid.h:41
avalanche
Definition: avalanche.h:11
avalanche::PeerManager::addNode
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
Definition: peermanager.cpp:17
avalanche::Slot::Slot
Slot(uint64_t startIn, uint32_t scoreIn, PeerId peeridIn)
Definition: peermanager.h:44
avalanche::PeerManager::orphanProofPool
ProofPool orphanProofPool
Definition: peermanager.h:131
avalanche::PeerManager::addUnbroadcastProof
void addUnbroadcastProof(const ProofId &proofid)
Proof broadcast API.
Definition: peermanager.cpp:604
avalanche::PeerManager::peers
PeerSet peers
Definition: peermanager.h:127
GetTime
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: time.cpp:27
avalanche::ProofId
Definition: proofid.h:17
avalanche::PeerManager::removeUnbroadcastProof
void removeUnbroadcastProof(const ProofId &proofid)
Definition: peermanager.cpp:611
avalanche::PeerManager::PeerSet
boost::multi_index_container< Peer, bmi::indexed_by< bmi::hashed_unique< bmi::member< Peer, PeerId, &Peer::peerid > >, bmi::hashed_unique< bmi::tag< by_proofid >, proof_index, SaltedProofIdHasher > >> PeerSet
Several nodes can make an avalanche peer.
Definition: peermanager.h:124
pubkey.h
proofpool.h
avalanche::Peer
Definition: peermanager.h:69
avalanche::PeerManager::PendingNodeSet
boost::multi_index_container< PendingNode, bmi::indexed_by< bmi::hashed_non_unique< bmi::tag< by_proofid >, bmi::member< PendingNode, ProofId, &PendingNode::proofid >, SaltedProofIdHasher >, bmi::hashed_unique< bmi::tag< by_nodeid >, bmi::member< PendingNode, NodeId, &PendingNode::nodeid > >> > PendingNodeSet
Definition: peermanager.h:158
avalanche::PeerManager::removeNodeFromPeer
bool removeNodeFromPeer(const PeerSet::iterator &it, uint32_t count=1)
Definition: peermanager.cpp:97
avalanche::PeerManager::isOrphan
bool isOrphan(const ProofId &proofid) const
Definition: peermanager.cpp:362
TimePoint
std::chrono::time_point< std::chrono::steady_clock > TimePoint
Definition: node.h:17
avalanche::Slot::peerid
PeerId peerid
Definition: peermanager.h:41
avalanche::Slot::getPeerId
PeerId getPeerId() const
Definition: peermanager.h:60
avalanche::PeerManager::updatedBlockTip
void updatedBlockTip()
Update the peer set when a new block is connected.
Definition: peermanager.cpp:288
avalanche::Slot::start
uint64_t start
Definition: peermanager.h:39
avalanche::PeerManager::exists
bool exists(const ProofId &proofid) const
Definition: peermanager.h:222
avalanche::selectPeerImpl
PeerId selectPeerImpl(const std::vector< Slot > &slots, const uint64_t slot, const uint64_t max)
Internal methods that are exposed for testing purposes.
Definition: peermanager.cpp:547
avalanche::Slot::getScore
uint32_t getScore() const
Definition: peermanager.h:59
avalanche::PeerManager::removePeer
bool removePeer(const PeerId peerid)
Remove an existing peer.
Definition: peermanager.cpp:370
avalanche::Node
Definition: node.h:21
avalanche::PeerManager::RegistrationMode::DEFAULT
@ DEFAULT
avalanche::proof_index::operator()
result_type operator()(const Peer &p) const
Definition: peermanager.h:91
avalanche::PeerManager
Definition: peermanager.h:109
time.h
avalanche::PendingNode::PendingNode
PendingNode(ProofId proofid_, NodeId nodeid_)
Definition: peermanager.h:100
avalanche::PeerManager::RegistrationMode
RegistrationMode
Registration mode.
Definition: peermanager.h:215
avalanche::PeerManager::addOrUpdateNode
bool addOrUpdateNode(const PeerSet::iterator &it, NodeId nodeid)
Definition: peermanager.cpp:32
avalanche::Peer::proof
ProofRef proof
Definition: peermanager.h:74
avalanche::PeerManager::SELECT_NODE_MAX_RETRY
static constexpr int SELECT_NODE_MAX_RETRY
Definition: peermanager.h:162
avalanche::PeerManager::removeNode
bool removeNode(NodeId nodeid)
Definition: peermanager.cpp:79
avalanche::PeerManager::validProofPool
ProofPool validProofPool
Definition: peermanager.h:129
avalanche::Slot::score
uint32_t score
Definition: peermanager.h:40
avalanche::Peer::getProofId
const ProofId & getProofId() const
Definition: peermanager.h:85
avalanche::Peer::node_count
uint32_t node_count
Definition: peermanager.h:72
avalanche::PeerManager::conflictingProofPool
ProofPool conflictingProofPool
Definition: peermanager.h:130
avalanche::Slot::follows
bool follows(uint64_t slot) const
Definition: peermanager.h:66
avalanche::PeerManager::NodeSet
boost::multi_index_container< Node, bmi::indexed_by< bmi::hashed_unique< bmi::member< Node, NodeId, &Node::nodeid > >, bmi::ordered_non_unique< bmi::tag< next_request_time >, bmi::composite_key< Node, bmi::member< Node, PeerId, &Node::peerid >, bmi::member< Node, TimePoint, &Node::nextRequestTime > >> >> NodeSet
Definition: peermanager.h:143
coins.h
avalanche::PeerManager::fragmentation
uint64_t fragmentation
Definition: peermanager.h:112
avalanche::PendingNode
Definition: peermanager.h:96
avalanche::PeerManager::getProof
ProofRef getProof(const ProofId &proofid) const
Definition: peermanager.cpp:338
avalanche::PeerManager::updateNextPossibleConflictTime
bool updateNextPossibleConflictTime(PeerId peerid, const std::chrono::seconds &nextTime)
Proof and Peer related API.
Definition: peermanager.cpp:150
avalanche::PeerManager::selectPeer
PeerId selectPeer() const
Randomly select a peer to poll.
Definition: peermanager.cpp:403
avalanche::PeerManager::getSlotCount
uint64_t getSlotCount() const
Definition: peermanager.h:277
avalanche::ProofPool
Map a proof to each utxo.
Definition: proofpool.h:51
avalanche::PeerManager::slots
std::vector< Slot > slots
Definition: peermanager.h:110
avalanche::PeerManager::forPeer
bool forPeer(const ProofId &proofid, Callable &&func) const
Definition: peermanager.h:227
avalanche::Peer::index
uint32_t index
Definition: peermanager.h:71
avalanche::PeerManager::getUnbroadcastProofs
auto getUnbroadcastProofs() const
Definition: peermanager.h:249
avalanche::PeerManager::addNodeToPeer
bool addNodeToPeer(const PeerSet::iterator &it)
Definition: peermanager.cpp:62
proof.h
avalanche::PeerManager::m_unbroadcast_proofids
std::unordered_set< ProofId, SaltedProofIdHasher > m_unbroadcast_proofids
Track proof ids to broadcast.
Definition: peermanager.h:167
avalanche::Slot::withScore
Slot withScore(uint64_t scoreIn) const
Definition: peermanager.h:50
avalanche::Peer::getScore
uint32_t getScore() const
Definition: peermanager.h:86
avalanche::Peer::peerid
PeerId peerid
Definition: peermanager.h:70
avalanche::PeerManager::isBoundToPeer
bool isBoundToPeer(const ProofId &proofid) const
Definition: peermanager.cpp:357
avalanche::proof_index
Definition: peermanager.h:89
avalanche::PeerManager::registerProof
bool registerProof(const ProofRef &proof, RegistrationMode mode=RegistrationMode::DEFAULT)
Definition: peermanager.cpp:167
avalanche::Slot::getStart
uint64_t getStart() const
Definition: peermanager.h:57
salteduint256hasher.h
NodeId
int64_t NodeId
Definition: nodeid.h:10
avalanche::PeerManager::slotCount
uint64_t slotCount
Definition: peermanager.h:111
avalanche::PendingNode::proofid
ProofId proofid
Definition: peermanager.h:97
avalanche::Slot::precedes
bool precedes(uint64_t slot) const
Definition: peermanager.h:65
avalanche::Peer::registration_time
std::chrono::seconds registration_time
Definition: peermanager.h:77
avalanche::ProofRef
std::shared_ptr< const Proof > ProofRef
Definition: proof.h:163
node.h
avalanche::PeerManager::isInConflictingPool
bool isInConflictingPool(const ProofId &proofid) const
Definition: peermanager.cpp:366
avalanche::PeerManager::forEachNode
void forEachNode(const Peer &peer, Callable &&func) const
Definition: peermanager.h:189
avalanche::Peer::nextPossibleConflictTime
std::chrono::seconds nextPossibleConflictTime
Definition: peermanager.h:78
avalanche::next_request_time
Definition: peermanager.h:94
avalanche::Slot::withStart
Slot withStart(uint64_t startIn) const
Definition: peermanager.h:47
avalanche::PeerManager::pendingNodes
PendingNodeSet pendingNodes
Definition: peermanager.h:159
PeerId
uint32_t PeerId
Definition: node.h:14
avalanche::PeerManager::getFragmentation
uint64_t getFragmentation() const
Definition: peermanager.h:278
avalanche::PeerManager::selectNode
NodeId selectNode()
Definition: peermanager.cpp:265
avalanche::PeerManager::RegistrationMode::FORCE_ACCEPT
@ FORCE_ACCEPT
avalanche::Slot::getStop
uint64_t getStop() const
Definition: peermanager.h:58
avalanche::PeerManager::forEachPeer
void forEachPeer(Callable &&func) const
Definition: peermanager.h:233
avalanche::Slot::contains
bool contains(uint64_t slot) const
Definition: peermanager.h:62