Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/peermanager.cpp
// Copyright (c) 2020 The Bitcoin developers | // Copyright (c) 2020 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <avalanche/peermanager.h> | #include <avalanche/peermanager.h> | ||||
#include <avalanche/delegation.h> | #include <avalanche/delegation.h> | ||||
#include <avalanche/validation.h> | #include <avalanche/validation.h> | ||||
#include <random.h> | #include <random.h> | ||||
#include <validation.h> // For ChainstateActive() | #include <validation.h> // For ChainstateActive() | ||||
#include <cassert> | #include <cassert> | ||||
namespace avalanche { | namespace avalanche { | ||||
bool PeerManager::addNode(NodeId nodeid, const Proof &proof, | bool PeerManager::addNode(NodeId nodeid, std::shared_ptr<Proof> proof, | ||||
const Delegation &delegation) { | const Delegation &delegation) { | ||||
auto it = fetchOrCreatePeer(proof); | DelegationState state; | ||||
deadalnix: Don't change the behavior in a middle of a refactoring. | |||||
if (it == peers.end()) { | CPubKey pubkey; | ||||
if (!delegation.verify(state, *proof, pubkey)) { | |||||
return false; | return false; | ||||
} | } | ||||
const PeerId peerid = it->peerid; | auto it = fetchOrCreatePeer(std::move(proof)); | ||||
deadalnixUnsubmitted Not Done Inline ActionsNo need for move if you pass by const ref. deadalnix: No need for move if you pass by const ref. | |||||
if (it == peers.end()) { | |||||
DelegationState state; | |||||
CPubKey pubkey; | |||||
if (!delegation.verify(state, proof, pubkey)) { | |||||
return false; | return false; | ||||
} | } | ||||
const PeerId peerid = it->peerid; | |||||
auto nit = nodes.find(nodeid); | auto nit = nodes.find(nodeid); | ||||
if (nit == nodes.end()) { | if (nit == nodes.end()) { | ||||
if (!nodes.emplace(nodeid, peerid, std::move(pubkey)).second) { | if (!nodes.emplace(nodeid, peerid, std::move(pubkey)).second) { | ||||
return false; | return false; | ||||
} | } | ||||
} else { | } else { | ||||
const PeerId oldpeerid = nit->peerid; | const PeerId oldpeerid = nit->peerid; | ||||
if (!nodes.modify(nit, [&](Node &n) { | if (!nodes.modify(nit, [&](Node &n) { | ||||
▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | std::vector<PeerId> invalidPeers; | ||||
} | } | ||||
} | } | ||||
for (const auto &pid : invalidPeers) { | for (const auto &pid : invalidPeers) { | ||||
removePeer(pid); | removePeer(pid); | ||||
} | } | ||||
} | } | ||||
PeerId PeerManager::getPeerId(const Proof &proof) { | PeerId PeerManager::getPeerId(std::shared_ptr<Proof> proof) { | ||||
auto it = fetchOrCreatePeer(proof); | auto it = fetchOrCreatePeer(std::move(proof)); | ||||
return it == peers.end() ? NO_PEER : it->peerid; | return it == peers.end() ? NO_PEER : it->peerid; | ||||
} | } | ||||
PeerManager::PeerSet::iterator | PeerManager::PeerSet::iterator | ||||
PeerManager::fetchOrCreatePeer(const Proof &proof) { | PeerManager::fetchOrCreatePeer(std::shared_ptr<Proof> proof) { | ||||
{ | { | ||||
// Check if we already know of that peer. | // Check if we already know of that peer. | ||||
auto &pview = peers.get<proof_index>(); | auto &pview = peers.get<proof_index>(); | ||||
auto it = pview.find(proof.getId()); | auto it = pview.find(proof->getId()); | ||||
if (it != pview.end()) { | if (it != pview.end()) { | ||||
return peers.project<0>(it); | return peers.project<0>(it); | ||||
} | } | ||||
} | } | ||||
{ | { | ||||
// Reject invalid proof. | // Reject invalid proof. | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | ||||
ProofValidationState state; | ProofValidationState state; | ||||
if (!proof.verify(state, coins)) { | if (!proof->verify(state, coins)) { | ||||
return peers.end(); | return peers.end(); | ||||
} | } | ||||
} | } | ||||
// New peer means new peerid! | // New peer means new peerid! | ||||
const PeerId peerid = nextPeerId++; | const PeerId peerid = nextPeerId++; | ||||
// Attach UTXOs to this proof. | // Attach UTXOs to this proof. | ||||
std::unordered_set<PeerId> conflicting_peerids; | std::unordered_set<PeerId> conflicting_peerids; | ||||
for (const auto &s : proof.getStakes()) { | for (const auto &s : proof->getStakes()) { | ||||
auto p = utxos.emplace(s.getStake().getUTXO(), peerid); | auto p = utxos.emplace(s.getStake().getUTXO(), peerid); | ||||
if (!p.second) { | if (!p.second) { | ||||
// We have a collision with an existing proof. | // We have a collision with an existing proof. | ||||
conflicting_peerids.insert(p.first->second); | conflicting_peerids.insert(p.first->second); | ||||
} | } | ||||
} | } | ||||
// For now, if there is a conflict, just ceanup the mess. | // For now, if there is a conflict, just ceanup the mess. | ||||
if (conflicting_peerids.size() > 0) { | if (conflicting_peerids.size() > 0) { | ||||
for (const auto &s : proof.getStakes()) { | for (const auto &s : proof->getStakes()) { | ||||
auto it = utxos.find(s.getStake().getUTXO()); | auto it = utxos.find(s.getStake().getUTXO()); | ||||
assert(it != utxos.end()); | assert(it != utxos.end()); | ||||
// We need to delete that one. | // We need to delete that one. | ||||
if (it->second == peerid) { | if (it->second == peerid) { | ||||
utxos.erase(it); | utxos.erase(it); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 226 Lines • Show Last 20 Lines |
Don't change the behavior in a middle of a refactoring.