Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche.h
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | static uint32_t countBits(uint32_t value) { | ||||
} | } | ||||
return count; | return count; | ||||
} | } | ||||
public: | public: | ||||
VoteRecord() : votes(0xaaaa), confidence(0) {} | VoteRecord() : votes(0xaaaa), confidence(0) {} | ||||
bool isValid() const { return confidence & 0x01; } | bool isAccepted() const { return confidence & 0x01; } | ||||
uint16_t getConfidence() const { return confidence >> 1; } | uint16_t getConfidence() const { return confidence >> 1; } | ||||
bool hasFinalized() const { | bool hasFinalized() const { | ||||
return getConfidence() >= AVALANCHE_FINALIZATION_SCORE; | return getConfidence() >= AVALANCHE_FINALIZATION_SCORE; | ||||
} | } | ||||
/** | |||||
* Register a new vote for an item and update confidence accordingly. | |||||
* Returns true if the acceptance or finalization state changed. | |||||
*/ | |||||
bool registerVote(bool vote) { | bool registerVote(bool vote) { | ||||
votes = (votes << 1) | vote; | votes = (votes << 1) | vote; | ||||
auto bits = countBits(votes & 0xff); | auto bits = countBits(votes & 0xff); | ||||
bool yes = bits > 6; | bool yes = bits > 6; | ||||
bool no = bits < 2; | bool no = bits < 2; | ||||
if (!yes && !no) { | if (!yes && !no) { | ||||
// The vote is inconclusive. | // The vote is inconclusive. | ||||
return false; | return false; | ||||
} | } | ||||
if (isValid() == yes) { | if (isAccepted() == yes) { | ||||
// If the vote is in agreement with our internal status, increase | // If the vote is in agreement with our internal status, increase | ||||
// confidence. | // confidence. | ||||
confidence += 2; | confidence += 2; | ||||
} else { | return getConfidence() == AVALANCHE_FINALIZATION_SCORE; | ||||
// The vote did not agree with our internal state, in that case, | |||||
// reset confidence. | |||||
confidence = yes; | |||||
} | } | ||||
// The vote did not agree with our internal state, in that case, reset | |||||
// confidence. | |||||
confidence = yes; | |||||
return true; | return true; | ||||
} | } | ||||
}; | }; | ||||
class AvalancheVote { | class AvalancheVote { | ||||
uint32_t error; | uint32_t error; | ||||
uint256 hash; | uint256 hash; | ||||
Show All 30 Lines | public: | ||||
template <typename Stream, typename Operation> | template <typename Stream, typename Operation> | ||||
inline void SerializationOp(Stream &s, Operation ser_action) { | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
READWRITE(cooldown); | READWRITE(cooldown); | ||||
READWRITE(votes); | READWRITE(votes); | ||||
} | } | ||||
}; | }; | ||||
class AvalancheBlockUpdate { | |||||
union { | |||||
CBlockIndex *pindex; | |||||
size_t raw; | |||||
}; | |||||
public: | |||||
enum Status : uint8_t { | |||||
Invalid, | |||||
Rejected, | |||||
Accepted, | |||||
Finalized, | |||||
}; | |||||
AvalancheBlockUpdate(CBlockIndex *pindexIn, Status statusIn) | |||||
: pindex(pindexIn) { | |||||
raw |= statusIn; | |||||
} | |||||
Status getStatus() const { return Status(raw & 0x03); } | |||||
CBlockIndex *getBlockIndex() { | |||||
return reinterpret_cast<CBlockIndex *>(raw & -size_t(0x04)); | |||||
} | |||||
const CBlockIndex *getBlockIndex() const { | |||||
return const_cast<AvalancheBlockUpdate *>(this)->getBlockIndex(); | |||||
} | |||||
}; | |||||
typedef std::map<const CBlockIndex *, VoteRecord, CBlockIndexWorkComparator> | typedef std::map<const CBlockIndex *, VoteRecord, CBlockIndexWorkComparator> | ||||
BlockVoteMap; | BlockVoteMap; | ||||
class AvalancheProcessor { | class AvalancheProcessor { | ||||
private: | private: | ||||
/** | /** | ||||
* Blocks to run avalanche on. | * Blocks to run avalanche on. | ||||
*/ | */ | ||||
Show All 9 Lines | private: | ||||
std::condition_variable cond_running; | std::condition_variable cond_running; | ||||
public: | public: | ||||
AvalancheProcessor() : stopRequest(false), running(false) {} | AvalancheProcessor() : stopRequest(false), running(false) {} | ||||
~AvalancheProcessor() { stopEventLoop(); } | ~AvalancheProcessor() { stopEventLoop(); } | ||||
bool addBlockToReconcile(const CBlockIndex *pindex); | bool addBlockToReconcile(const CBlockIndex *pindex); | ||||
bool isAccepted(const CBlockIndex *pindex) const; | bool isAccepted(const CBlockIndex *pindex) const; | ||||
bool hasFinalized(const CBlockIndex *pindex) const; | |||||
bool registerVotes(const AvalancheResponse &response); | bool registerVotes(const AvalancheResponse &response, | ||||
std::vector<AvalancheBlockUpdate> &updates); | |||||
bool startEventLoop(CScheduler &scheduler); | bool startEventLoop(CScheduler &scheduler); | ||||
bool stopEventLoop(); | bool stopEventLoop(); | ||||
private: | private: | ||||
std::vector<CInv> getInvsForNextPoll() const; | std::vector<CInv> getInvsForNextPoll() const; | ||||
friend struct AvalancheTest; | friend struct AvalancheTest; | ||||
}; | }; | ||||
#endif // BITCOIN_AVALANCHE_H | #endif // BITCOIN_AVALANCHE_H |