Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche.cpp
Show All 25 Lines | #else | ||||
* https://www.playingwithpointers.com/blog/swar.html | * https://www.playingwithpointers.com/blog/swar.html | ||||
*/ | */ | ||||
v = v - ((v >> 1) & 0x55555555); | v = v - ((v >> 1) & 0x55555555); | ||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); | v = (v & 0x33333333) + ((v >> 2) & 0x33333333); | ||||
return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; | return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; | ||||
#endif | #endif | ||||
} | } | ||||
bool VoteRecord::registerVote(bool vote) { | bool VoteRecord::registerVote(uint32_t error) { | ||||
votes = (votes << 1) | vote; | /** | ||||
* The result of the vote is determined from the error code. If the error | |||||
* code is 0, there is no error and therefore the vote is yes. If there is | |||||
* an error, we check the most signficant bit to decide if the vote is a no | |||||
* (for instance, the block is invalid) or is the vote inconclusive (for | |||||
* instance, the queried node do not have the block yet). | |||||
*/ | |||||
votes = (votes << 1) | (error == 0); | |||||
consider = (consider << 1) | (int32_t(error) >= 0); | |||||
auto bits = countBits(votes & 0xff); | /** | ||||
bool yes = bits > 6; | * We compute the number of yes and/or no votes as follow: | ||||
bool no = bits < 2; | * | ||||
if (!yes && !no) { | * votes: 1010 | ||||
// The vote is inconclusive. | * consider: 1100 | ||||
* | |||||
* yes votes: 1000 using votes & consider | |||||
* no votes: 0100 using ~votes & consider | |||||
*/ | |||||
bool yes = countBits(votes & consider & 0xff) > 6; | |||||
if (!yes) { | |||||
bool no = countBits(~votes & consider & 0xff) > 6; | |||||
if (!no) { | |||||
// The round is inconclusive. | |||||
return false; | return false; | ||||
} | } | ||||
} | |||||
// If the round is in agreement with previous rounds, increase confidence. | |||||
if (isAccepted() == yes) { | if (isAccepted() == yes) { | ||||
// If the vote is in agreement with our internal status, increase | |||||
// confidence. | |||||
confidence += 2; | confidence += 2; | ||||
return getConfidence() == AVALANCHE_FINALIZATION_SCORE; | return getConfidence() == AVALANCHE_FINALIZATION_SCORE; | ||||
} | } | ||||
// The vote did not agree with our internal state, in that case, reset | // The round changed our state. We reset the confidence. | ||||
// confidence. | |||||
confidence = yes; | confidence = yes; | ||||
return true; | return true; | ||||
} | } | ||||
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()) { | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
bool AvalancheProcessor::isAccepted(const CBlockIndex *pindex) const { | bool AvalancheProcessor::isAccepted(const CBlockIndex *pindex) const { | ||||
if (auto vr = GetRecord(vote_records, pindex)) { | if (auto vr = GetRecord(vote_records, pindex)) { | ||||
return vr->isAccepted(); | return vr->isAccepted(); | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
int AvalancheProcessor::getConfidence(const CBlockIndex *pindex) const { | |||||
if (auto vr = GetRecord(vote_records, pindex)) { | |||||
return vr->getConfidence(); | |||||
} | |||||
return -1; | |||||
} | |||||
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 w = peerSet.getWriteView(); | auto w = peerSet.getWriteView(); | ||||
auto it = w->find(nodeid); | auto it = w->find(nodeid); | ||||
if (it != w->end()) { | if (it != w->end()) { | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | std::map<CBlockIndex *, AvalancheVote> responseIndex; | ||||
auto it = w->find(pindex); | auto it = w->find(pindex); | ||||
if (it == w.end()) { | if (it == w.end()) { | ||||
// We are not voting on that item anymore. | // We are not voting on that item anymore. | ||||
continue; | continue; | ||||
} | } | ||||
auto &vr = it->second; | auto &vr = it->second; | ||||
if (!vr.registerVote(v.IsValid())) { | if (!vr.registerVote(v.GetError())) { | ||||
// This vote did not provide any extra information, move on. | // This vote did not provide any extra information, move on. | ||||
continue; | continue; | ||||
} | } | ||||
if (!vr.hasFinalized()) { | if (!vr.hasFinalized()) { | ||||
// This item has note been finalized, so we have nothing more to | // This item has note been finalized, so we have nothing more to | ||||
// do. | // do. | ||||
updates.emplace_back( | updates.emplace_back( | ||||
▲ Show 20 Lines • Show All 187 Lines • Show Last 20 Lines |