Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche.cpp
// Copyright (c) 2018 The Bitcoin developers | // Copyright (c) 2018 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.h" | #include "avalanche.h" | ||||
#include "chain.h" | #include "chain.h" | ||||
#include "netmessagemaker.h" | #include "netmessagemaker.h" | ||||
#include "scheduler.h" | #include "scheduler.h" | ||||
#include "validation.h" | #include "validation.h" | ||||
#include <boost/range/adaptor/reversed.hpp> | #include <boost/range/adaptor/reversed.hpp> | ||||
#include <tuple> | |||||
static bool IsWorthPolling(const CBlockIndex *pindex) { | static bool IsWorthPolling(const CBlockIndex *pindex) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (pindex->nStatus.isInvalid()) { | if (pindex->nStatus.isInvalid()) { | ||||
// No point polling invalid blocks. | // No point polling invalid blocks. | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
bool AvalancheProcessor::registerVotes( | bool AvalancheProcessor::registerVotes( | ||||
NodeId nodeid, const AvalancheResponse &response, | NodeId nodeid, const AvalancheResponse &response, | ||||
std::vector<AvalancheBlockUpdate> &updates) { | std::vector<AvalancheBlockUpdate> &updates) { | ||||
// Save the time at which we can query again. | // Save the time at which we can query again. | ||||
auto cooldown_end = std::chrono::steady_clock::now() + | auto cooldown_end = std::chrono::steady_clock::now() + | ||||
std::chrono::milliseconds(response.getCooldown()); | std::chrono::milliseconds(response.getCooldown()); | ||||
RequestRecord r; | std::vector<CInv> invs; | ||||
{ | { | ||||
// Check that the query exists. | // Check that the query exists. | ||||
auto w = queries.getWriteView(); | auto w = queries.getWriteView(); | ||||
auto it = w->find(nodeid); | auto it = w->find(std::make_tuple(nodeid, response.getRound())); | ||||
if (it == w.end()) { | if (it == w.end()) { | ||||
// NB: The request may be old, so we don't increase banscore. | // NB: The request may be old, so we don't increase banscore. | ||||
return false; | return false; | ||||
} | } | ||||
r = std::move(it->second); | invs = std::move(it->invs); | ||||
w->erase(it); | w->erase(it); | ||||
} | } | ||||
// Verify that the request and the vote are consistent. | // Verify that the request and the vote are consistent. | ||||
const std::vector<CInv> &invs = r.GetInvs(); | |||||
const std::vector<AvalancheVote> &votes = response.GetVotes(); | const std::vector<AvalancheVote> &votes = response.GetVotes(); | ||||
size_t size = invs.size(); | size_t size = invs.size(); | ||||
if (votes.size() != size) { | if (votes.size() != size) { | ||||
// TODO: increase banscore for inconsistent response. | // TODO: increase banscore for inconsistent response. | ||||
// NB: This isn't timeout but actually node misbehaving. | // NB: This isn't timeout but actually node misbehaving. | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 215 Lines • ▼ Show 20 Lines | void AvalancheProcessor::runEventLoop() { | ||||
/** | /** | ||||
* If we lost contact to that node, then we remove it from nodeids, but | * If we lost contact to that node, then we remove it from nodeids, but | ||||
* never add the request to queries, which ensures bad nodes get cleaned up | * never add the request to queries, which ensures bad nodes get cleaned up | ||||
* over time. | * over time. | ||||
*/ | */ | ||||
connman->ForNode(nodeid, [this, &invs](CNode *pnode) { | connman->ForNode(nodeid, [this, &invs](CNode *pnode) { | ||||
{ | { | ||||
// Compute the time at which this requests times out. | |||||
auto timeout = | |||||
std::chrono::steady_clock::now() + std::chrono::seconds(10); | |||||
// Register the query. | // Register the query. | ||||
queries.getWriteView()->emplace( | queries.getWriteView()->insert( | ||||
pnode->GetId(), RequestRecord(GetAdjustedTime(), invs)); | {pnode->GetId(), round, timeout, invs}); | ||||
} | } | ||||
// Send the query to the node. | // Send the query to the node. | ||||
connman->PushMessage( | connman->PushMessage( | ||||
pnode, | pnode, | ||||
CNetMsgMaker(pnode->GetSendVersion()) | CNetMsgMaker(pnode->GetSendVersion()) | ||||
.Make(NetMsgType::AVAPOLL, | .Make(NetMsgType::AVAPOLL, | ||||
AvalanchePoll(round++, std::move(invs)))); | AvalanchePoll(round++, std::move(invs)))); | ||||
return true; | return true; | ||||
}); | }); | ||||
} | } |