19 if (it ==
peers.end()) {
23 const PeerId peerid = it->peerid;
27 if (!delegation.
verify(state, proof, pubkey)) {
31 auto nit =
nodes.find(nodeid);
32 if (nit ==
nodes.end()) {
33 if (!
nodes.emplace(nodeid, peerid, std::move(pubkey)).second) {
37 const PeerId oldpeerid = nit->peerid;
40 n.pubkey = std::move(pubkey);
50 it =
peers.find(peerid);
60 assert(it !=
peers.end());
71 slots.emplace_back(start, score, it->peerid);
77 auto it =
nodes.find(nodeid);
78 if (it ==
nodes.end()) {
82 const PeerId peerid = it->peerid;
94 assert(it !=
peers.end());
95 assert(count <= it->node_count);
101 const uint32_t new_count = it->node_count -
count;
102 if (!
peers.modify(it, [&](
Peer &p) { p.node_count = new_count; })) {
112 const size_t i = it->index;
113 assert(i <
slots.size());
114 if (i + 1 ==
slots.size()) {
126 std::function<
bool(
const Node &n)> func)
const {
127 auto it =
nodes.find(nodeid);
128 return it !=
nodes.end() && func(*it);
132 auto it =
nodes.find(nodeid);
133 if (it ==
nodes.end()) {
153 auto it = nview.lower_bound(boost::make_tuple(p,
TimePoint()));
154 if (it != nview.end() && it->peerid == p &&
155 it->nextRequestTime <= std::chrono::steady_clock::now()) {
164 std::vector<PeerId> invalidPeers;
170 for (
const auto &p :
peers) {
172 if (!p.proof.verify(state, coins)) {
173 invalidPeers.push_back(p.peerid);
178 for (
const auto &pid : invalidPeers) {
188 PeerManager::PeerSet::iterator
193 auto it = pview.find(proof.
getId());
194 if (it != pview.end()) {
195 return peers.project<0>(it);
205 if (!proof.
verify(state, coins)) {
214 std::unordered_set<PeerId> conflicting_peerids;
215 for (
const auto &s : proof.
getStakes()) {
216 auto p =
utxos.emplace(s.getStake().getUTXO(), peerid);
219 conflicting_peerids.insert(p.first->second);
224 if (conflicting_peerids.size() > 0) {
225 for (
const auto &s : proof.
getStakes()) {
226 auto it =
utxos.find(s.getStake().getUTXO());
227 assert(it !=
utxos.end());
230 if (it->second == peerid) {
239 auto inserted =
peers.emplace(peerid, proof);
240 assert(inserted.second);
242 return inserted.first;
246 auto it =
peers.find(peerid);
247 if (it ==
peers.end()) {
258 nview.erase(nview.lower_bound(boost::make_tuple(peerid,
TimePoint())),
259 nview.upper_bound(boost::make_tuple(
260 peerid, std::chrono::steady_clock::now())));
263 for (
const auto &s : it->proof.getStakes()) {
264 bool deleted =
utxos.erase(s.getStake().getUTXO()) > 0;
294 std::vector<Slot> newslots;
295 newslots.reserve(
peers.size());
297 uint64_t prevStop = 0;
299 for (
auto it =
peers.begin(); it !=
peers.end(); it++) {
300 if (it->node_count == 0) {
304 newslots.emplace_back(prevStop, it->getScore(), it->peerid);
305 prevStop =
slots[i].getStop();
306 if (!
peers.modify(it, [&](
Peer &p) { p.index = i++; })) {
311 slots = std::move(newslots);
313 const uint64_t saved =
slotCount - prevStop;
321 uint64_t prevStop = 0;
322 for (
size_t i = 0; i <
slots.size(); i++) {
339 if (it ==
peers.end() || it->index != i) {
344 for (
const auto &p :
peers) {
346 const auto count_nodes = [&]() {
350 nview.lower_bound(boost::make_tuple(p.peerid,
TimePoint()));
352 nview.upper_bound(boost::make_tuple(p.peerid + 1,
TimePoint()));
354 for (
auto it = begin; it != end; ++it) {
361 if (p.node_count != count_nodes()) {
366 if (p.node_count == 0) {
371 if (p.index >=
slots.size() ||
slots[p.index].getPeerId() != p.peerid) {
376 if (
slots[p.index].getScore() != p.getScore()) {
385 const uint64_t max) {
388 size_t begin = 0, end = slots.size();
389 uint64_t bottom = 0, top = max;
392 while ((end - begin) > 8) {
394 if (slot < bottom || slot >= top) {
399 size_t i = begin + ((slot - bottom) * (end - begin) / (top - bottom));
400 assert(begin <= i && i < end);
403 if (slots[i].contains(slot)) {
404 return slots[i].getPeerId();
408 if (slots[i].precedes(slot)) {
414 bottom = slots[begin].getStart();
419 if (slots[i].follows(slot)) {
421 top = slots[end].getStart();
430 for (
size_t i = begin; i < end; i++) {
432 if (slots[i].contains(slot)) {
433 return slots[i].getPeerId();
uint64_t compact()
Trigger maintenance of internal datastructures.
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
uint64_t GetRand(uint64_t nMax) noexcept
bool removeNode(NodeId nodeid)
const std::vector< SignedStake > & getStakes() const
bool verify() const
Perform consistency check on internal data structures.
bool verify(DelegationState &state, const Proof &proof, CPubKey &auth) const
bool removeNodeFromPeer(const PeerSet::iterator &it, uint32_t count=1)
bool updateNextRequestTime(NodeId nodeid, TimePoint timeout)
PeerId selectPeer() const
Randomly select a peer to poll.
PeerId selectPeerImpl(const std::vector< Slot > &slots, const uint64_t slot, const uint64_t max)
This is an internal method that is exposed for testing purposes.
CChainState & ChainstateActive()
NodeId selectNode()
Randomly select a node to poll.
uint64_t getStart() const
bool addNodeToPeer(const PeerSet::iterator &it)
An encapsulated public key.
uint32_t getScore() const
bool addNode(NodeId nodeid, const Proof &proof, const Delegation &delegation)
Node API.
RecursiveMutex cs_main
Global state.
PeerSet::iterator fetchOrCreatePeer(const Proof &proof)
bool verify(ProofValidationState &state) const
bool removePeer(const PeerId peerid)
Remove an existing peer.
const ProofId & getId() const
TimePoint nextRequestTime
static constexpr int SELECT_PEER_MAX_RETRY
std::vector< Slot > slots
PeerId getPeerId(const Proof &proof)
Provide the PeerId associated with the given proof.
std::chrono::time_point< std::chrono::steady_clock > TimePoint
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::unordered_map< COutPoint, PeerId, SaltedOutpointHasher > utxos
CCoinsView that adds a memory cache for transactions to another CCoinsView.
static constexpr int SELECT_NODE_MAX_RETRY
static constexpr PeerId NO_PEER
void updatedBlockTip()
Update the peer set when a nw block is connected.
bool forNode(NodeId nodeid, std::function< bool(const Node &n)> func) const