Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche.cpp
Show First 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | bool AvalancheProcessor::isAccepted(const CBlockIndex *pindex) const { | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
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. | |||||
auto cooldown_end = std::chrono::steady_clock::now() + | |||||
jasonbcox: Is there a reason we're departing from GetTime() / GetTimeMillis() / GetTimeMicros()? If… | |||||
deadalnixAuthorUnsubmitted Done Inline ActionsThese times can be mocked. They use an ancestor of chrono from boost under the hood. deadalnix: These times can be mocked. They use an ancestor of chrono from boost under the hood. | |||||
std::chrono::milliseconds(response.getCooldown()); | |||||
RequestRecord r; | RequestRecord r; | ||||
{ | { | ||||
// 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(nodeid); | ||||
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. | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | std::map<CBlockIndex *, AvalancheVote> responseIndex; | ||||
vr.isAccepted() | vr.isAccepted() | ||||
? AvalancheBlockUpdate::Status::Finalized | ? AvalancheBlockUpdate::Status::Finalized | ||||
: AvalancheBlockUpdate::Status::Invalid); | : AvalancheBlockUpdate::Status::Invalid); | ||||
w->erase(it); | w->erase(it); | ||||
} | } | ||||
} | } | ||||
// Put the node back in the list of queriable nodes. | // Put the node back in the list of queriable nodes. | ||||
auto w = nodeids.getWriteView(); | auto w = nodecooldown.getWriteView(); | ||||
w->insert(nodeid); | w->insert(std::make_pair(cooldown_end, nodeid)); | ||||
return true; | return true; | ||||
} | } | ||||
namespace { | namespace { | ||||
/** | /** | ||||
* Run the avalanche event loop every 10ms. | * Run the avalanche event loop every 10ms. | ||||
*/ | */ | ||||
static int64_t AVALANCHE_TIME_STEP_MILLISECONDS = 10; | static int64_t AVALANCHE_TIME_STEP_MILLISECONDS = 10; | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | for (const std::pair<const CBlockIndex *, VoteRecord> &p : | ||||
} | } | ||||
} | } | ||||
return invs; | return invs; | ||||
} | } | ||||
NodeId AvalancheProcessor::getSuitableNodeToQuery() { | NodeId AvalancheProcessor::getSuitableNodeToQuery() { | ||||
auto w = nodeids.getWriteView(); | auto w = nodeids.getWriteView(); | ||||
if (w->empty()) { | bool isCooldownMapEmpty; | ||||
{ | |||||
// Recover nodes for which cooldown is over. | |||||
auto now = std::chrono::steady_clock::now(); | |||||
auto wcooldown = nodecooldown.getWriteView(); | |||||
for (auto it = wcooldown.begin(); | |||||
it != wcooldown.end() && it->first < now;) { | |||||
w->insert(it->second); | |||||
wcooldown->erase(it++); | |||||
} | |||||
isCooldownMapEmpty = wcooldown->empty(); | |||||
} | |||||
// If the cooldown map is empty and we don't have any nodes, it's time to | |||||
// fish for new ones. | |||||
// FIXME: Clearly, we need a better way to fish for new nodes, but this is | |||||
// out of scope for now. | |||||
if (isCooldownMapEmpty && w->empty()) { | |||||
auto r = queries.getReadView(); | auto r = queries.getReadView(); | ||||
// We don't have any candidate node, so let's try to find some. | // We don't have any candidate node, so let's try to find some. | ||||
connman->ForEachNode([&w, &r](CNode *pnode) { | connman->ForEachNode([&w, &r](CNode *pnode) { | ||||
// If this node doesn't support avalanche, we remove. | // If this node doesn't support avalanche, we remove. | ||||
if (!(pnode->nServices & NODE_AVALANCHE)) { | if (!(pnode->nServices & NODE_AVALANCHE)) { | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 52 Lines • Show Last 20 Lines |
Is there a reason we're departing from GetTime() / GetTimeMillis() / GetTimeMicros()? If chrono is strictly better, then we should begin migrating away from the current GetTime implementation (in separate diffs, obviously).