Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/peermanager.cpp
Show First 20 Lines • Show All 248 Lines • ▼ Show 20 Lines | |||||
bool PeerManager::isOrphan(const ProofId &proofid) const { | bool PeerManager::isOrphan(const ProofId &proofid) const { | ||||
return orphanProofs.getProof(proofid) != nullptr; | return orphanProofs.getProof(proofid) != nullptr; | ||||
} | } | ||||
bool PeerManager::createPeer(const ProofRef &proof) { | bool PeerManager::createPeer(const ProofRef &proof) { | ||||
assert(proof); | assert(proof); | ||||
const ProofId &proofid = proof->getId(); | switch (validProofPool.addProof(proof)) { | ||||
case ProofPool::AddProofStatus::REJECTED: | |||||
if (isBoundToPeer(proofid)) { | // The proof has conflicts, orphan the proof so it can be pulled | ||||
// back if the conflicting ones are invalidated. | |||||
orphanProofs.addProof(proof); | |||||
return false; | return false; | ||||
case ProofPool::AddProofStatus::DUPLICATED: | |||||
// If the proof was already in the pool, don't duplicate the peer. | |||||
return false; | |||||
case ProofPool::AddProofStatus::SUCCEED: | |||||
break; | |||||
// No default case, so the compiler can warn about missing cases | |||||
} | } | ||||
// New peer means new peerid! | // New peer means new peerid! | ||||
const PeerId peerid = nextPeerId++; | const PeerId peerid = nextPeerId++; | ||||
// Attach UTXOs to this proof. | |||||
std::unordered_set<ProofRef> conflicting_proofs; | |||||
for (size_t i = 0; i < proof->getStakes().size(); i++) { | |||||
auto p = validProofPool.emplace(i, proof); | |||||
if (!p.second) { | |||||
// We have a collision with an existing proof. | |||||
conflicting_proofs.insert(p.first->proof); | |||||
} | |||||
} | |||||
// For now, if there is a conflict, just cleanup the mess. | |||||
if (conflicting_proofs.size() > 0) { | |||||
for (const auto &s : proof->getStakes()) { | |||||
auto it = validProofPool.find(s.getStake().getUTXO()); | |||||
assert(it != validProofPool.end()); | |||||
// We need to delete that one. | |||||
if (it->proof->getId() == proofid) { | |||||
validProofPool.erase(it); | |||||
} | |||||
} | |||||
// Orphan the proof so it can be pulled back if the conflicting ones are | |||||
// invalidated. | |||||
orphanProofs.addProof(proof); | |||||
return false; | |||||
} | |||||
// We have no peer for this proof, time to create it. | // We have no peer for this proof, time to create it. | ||||
auto inserted = peers.emplace(peerid, proof); | auto inserted = peers.emplace(peerid, proof); | ||||
assert(inserted.second); | assert(inserted.second); | ||||
// If there are nodes waiting for this proof, add them | // If there are nodes waiting for this proof, add them | ||||
auto &pendingNodesView = pendingNodes.get<by_proofid>(); | auto &pendingNodesView = pendingNodes.get<by_proofid>(); | ||||
auto range = pendingNodesView.equal_range(proofid); | auto range = pendingNodesView.equal_range(proof->getId()); | ||||
// We want to update the nodes then remove them from the pending set. That | // We want to update the nodes then remove them from the pending set. That | ||||
// will invalidate the range iterators, so we need to save the node ids | // will invalidate the range iterators, so we need to save the node ids | ||||
// first before we can loop over them. | // first before we can loop over them. | ||||
std::vector<NodeId> nodeids; | std::vector<NodeId> nodeids; | ||||
nodeids.reserve(std::distance(range.first, range.second)); | nodeids.reserve(std::distance(range.first, range.second)); | ||||
std::transform(range.first, range.second, std::back_inserter(nodeids), | std::transform(range.first, range.second, std::back_inserter(nodeids), | ||||
[](const PendingNode &n) { return n.nodeid; }); | [](const PendingNode &n) { return n.nodeid; }); | ||||
Show All 25 Lines | bool PeerManager::removePeer(const PeerId peerid) { | ||||
// Remove nodes associated with this peer, unless their timeout is still | // Remove nodes associated with this peer, unless their timeout is still | ||||
// active. This ensure that we don't overquery them in case they are | // active. This ensure that we don't overquery them in case they are | ||||
// subsequently added to another peer. | // subsequently added to another peer. | ||||
nview.erase(nview.lower_bound(boost::make_tuple(peerid, TimePoint())), | nview.erase(nview.lower_bound(boost::make_tuple(peerid, TimePoint())), | ||||
nview.upper_bound(boost::make_tuple( | nview.upper_bound(boost::make_tuple( | ||||
peerid, std::chrono::steady_clock::now()))); | peerid, std::chrono::steady_clock::now()))); | ||||
// Release UTXOs attached to this proof. | // Release UTXOs attached to this proof. | ||||
for (const auto &s : it->proof->getStakes()) { | validProofPool.removeProof(it->proof); | ||||
bool deleted = validProofPool.erase(s.getStake().getUTXO()) > 0; | |||||
assert(deleted); | |||||
} | |||||
m_unbroadcast_proofids.erase(it->proof->getId()); | m_unbroadcast_proofids.erase(it->proof->getId()); | ||||
peers.erase(it); | peers.erase(it); | ||||
return true; | return true; | ||||
} | } | ||||
PeerId PeerManager::selectPeer() const { | PeerId PeerManager::selectPeer() const { | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | bool PeerManager::verify() const { | ||||
for (const auto &p : peers) { | for (const auto &p : peers) { | ||||
// A peer should have a proof attached | // A peer should have a proof attached | ||||
if (!p.proof) { | if (!p.proof) { | ||||
return false; | return false; | ||||
} | } | ||||
// Check proof pool consistency | // Check proof pool consistency | ||||
for (const auto &ss : p.proof->getStakes()) { | for (const auto &ss : p.proof->getStakes()) { | ||||
auto it = validProofPool.find(ss.getStake().getUTXO()); | auto it = validProofPool.pool.find(ss.getStake().getUTXO()); | ||||
if (it == validProofPool.end()) { | if (it == validProofPool.pool.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
if (it->proof->getId() != p.getProofId()) { | if (it->proof->getId() != p.getProofId()) { | ||||
return false; | return false; | ||||
} | } | ||||
if (!peersUtxos.emplace(it->getUTXO()).second) { | if (!peersUtxos.emplace(it->getUTXO()).second) { | ||||
return false; | return false; | ||||
Show All 32 Lines | for (const auto &p : peers) { | ||||
// If the score do not match, same thing. | // If the score do not match, same thing. | ||||
if (slots[p.index].getScore() != p.getScore()) { | if (slots[p.index].getScore() != p.getScore()) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Check there is no dangling utxo | // Check there is no dangling utxo | ||||
for (const auto &entry : validProofPool) { | for (const auto &entry : validProofPool.pool) { | ||||
if (!peersUtxos.count(entry.getUTXO())) { | if (!peersUtxos.count(entry.getUTXO())) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 69 Lines • Show Last 20 Lines |