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 { | ||||
PeerManager::PeerManager() | |||||
: rejectedProofs( | |||||
// This filter uses the same parameters as the tx recentRejects. | |||||
std::make_unique<CRollingBloomFilter>(120000, 0.000001)) {} | |||||
bool PeerManager::addNode(NodeId nodeid, const Proof &proof, | bool PeerManager::addNode(NodeId nodeid, const Proof &proof, | ||||
const Delegation &delegation) { | const Delegation &delegation) { | ||||
auto it = fetchOrCreatePeer(proof); | auto it = fetchOrCreatePeer(proof); | ||||
if (it == peers.end()) { | if (it == peers.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
const PeerId peerid = it->peerid; | const PeerId peerid = it->peerid; | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | void PeerManager::updatedBlockTip() { | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | const CCoinsViewCache &coins = ::ChainstateActive().CoinsTip(); | ||||
for (const auto &p : peers) { | for (const auto &p : peers) { | ||||
ProofValidationState state; | ProofValidationState state; | ||||
if (!p.proof.verify(state, coins)) { | if (!p.proof.verify(state, coins)) { | ||||
invalidPeers.push_back(p.peerid); | invalidPeers.push_back(p.peerid); | ||||
if (state.GetResult() != ProofValidationResult::MISSING_UTXO) { | |||||
deadalnix: Why is this checking for this specific state? | |||||
PiRKAuthorUnsubmitted Done Inline ActionsBecause the orphan proofs will go into another pool. PiRK: Because the orphan proofs will go into another pool. | |||||
rejectedProofs->insert(p.proof.getId()); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
for (const auto &pid : invalidPeers) { | for (const auto &pid : invalidPeers) { | ||||
removePeer(pid); | removePeer(pid); | ||||
} | } | ||||
} | } | ||||
Show All 9 Lines | PeerManager::fetchOrCreatePeer(const 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); | ||||
} | } | ||||
} | } | ||||
if (rejectedProofs->contains(proof.getId())) { | |||||
return peers.end(); | |||||
deadalnixUnsubmitted Not Done Inline ActionsI'm not sure this makes sense. This check is probabilistic, it it shouldn't be there, but somewhere between the network on here. this definitively raises the question: should this filter be in the PeerManager at all? deadalnix: I'm not sure this makes sense. This check is probabilistic, it it shouldn't be there, but… | |||||
PiRKAuthorUnsubmitted Done Inline ActionsHaving the filter in the PeerManager is an easy way to fit it in the existing codebase and avoid having the network layer deal with proof verifications. The PeerManager is where proofs are currently verified and stored (if they are good). I thought about putting it elsewhere, but it requires some clumsy forwarding of ProofValidationState, if we want to avoid checking a proof twice (this is a previous attempt at doing that : https://reviews.bitcoinabc.org/D9417). PiRK: Having the filter in the PeerManager is an easy way to fit it in the existing codebase and… | |||||
} | |||||
{ | { | ||||
// 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)) { | ||||
if (state.GetResult() != ProofValidationResult::MISSING_UTXO) { | |||||
rejectedProofs->insert(proof.getId()); | |||||
} | |||||
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. | ||||
▲ Show 20 Lines • Show All 237 Lines • ▼ Show 20 Lines | std::vector<NodeId> PeerManager::getNodeIdsForPeer(PeerId peerId) const { | ||||
auto &nview = nodes.get<next_request_time>(); | auto &nview = nodes.get<next_request_time>(); | ||||
auto nodeRange = nview.equal_range(peerId); | auto nodeRange = nview.equal_range(peerId); | ||||
for (auto it = nodeRange.first; it != nodeRange.second; ++it) { | for (auto it = nodeRange.first; it != nodeRange.second; ++it) { | ||||
nodeids.emplace_back(it->nodeid); | nodeids.emplace_back(it->nodeid); | ||||
} | } | ||||
return nodeids; | return nodeids; | ||||
} | } | ||||
void PeerManager::rejectProof(ProofId proofId) { | |||||
rejectedProofs->insert(proofId); | |||||
} | |||||
} // namespace avalanche | } // namespace avalanche |
Why is this checking for this specific state?