Changeset View
Changeset View
Standalone View
Standalone View
src/avalanche/processor.cpp
Show First 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | void updatedBlockTip() override { | ||||
auto registeredProofs = registerProofs(); | auto registeredProofs = registerProofs(); | ||||
for (const auto &proof : registeredProofs) { | for (const auto &proof : registeredProofs) { | ||||
m_processor->addProofToReconcile(proof); | m_processor->addProofToReconcile(proof); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
Processor::Processor(const ArgsManager &argsman, interfaces::Chain &chain, | Processor::Processor(const ArgsManager &argsman, interfaces::Chain &chain, | ||||
CConnman *connmanIn, CScheduler &scheduler, | CConnman *connmanIn, ChainstateManager &chainmanIn, | ||||
CScheduler &scheduler, | |||||
std::unique_ptr<PeerData> peerDataIn, CKey sessionKeyIn, | std::unique_ptr<PeerData> peerDataIn, CKey sessionKeyIn, | ||||
uint32_t minQuorumTotalScoreIn, | uint32_t minQuorumTotalScoreIn, | ||||
double minQuorumConnectedScoreRatioIn, | double minQuorumConnectedScoreRatioIn, | ||||
int64_t minAvaproofsNodeCountIn, | int64_t minAvaproofsNodeCountIn, | ||||
uint32_t staleVoteThresholdIn, uint32_t staleVoteFactorIn) | uint32_t staleVoteThresholdIn, uint32_t staleVoteFactorIn) | ||||
: connman(connmanIn), | : connman(connmanIn), chainman(chainmanIn), | ||||
queryTimeoutDuration(argsman.GetArg( | queryTimeoutDuration(argsman.GetArg( | ||||
"-avatimeout", AVALANCHE_DEFAULT_QUERY_TIMEOUT.count())), | "-avatimeout", AVALANCHE_DEFAULT_QUERY_TIMEOUT.count())), | ||||
round(0), peerManager(std::make_unique<PeerManager>()), | round(0), peerManager(std::make_unique<PeerManager>()), | ||||
peerData(std::move(peerDataIn)), sessionKey(std::move(sessionKeyIn)), | peerData(std::move(peerDataIn)), sessionKey(std::move(sessionKeyIn)), | ||||
minQuorumScore(minQuorumTotalScoreIn), | minQuorumScore(minQuorumTotalScoreIn), | ||||
minQuorumConnectedScoreRatio(minQuorumConnectedScoreRatioIn), | minQuorumConnectedScoreRatio(minQuorumConnectedScoreRatioIn), | ||||
minAvaproofsNodeCount(minAvaproofsNodeCountIn), | minAvaproofsNodeCount(minAvaproofsNodeCountIn), | ||||
staleVoteThreshold(staleVoteThresholdIn), | staleVoteThreshold(staleVoteThresholdIn), | ||||
Show All 10 Lines | scheduler.scheduleEvery( | ||||
5min); | 5min); | ||||
} | } | ||||
Processor::~Processor() { | Processor::~Processor() { | ||||
chainNotificationsHandler.reset(); | chainNotificationsHandler.reset(); | ||||
stopEventLoop(); | stopEventLoop(); | ||||
} | } | ||||
std::unique_ptr<Processor> Processor::MakeProcessor(const ArgsManager &argsman, | std::unique_ptr<Processor> | ||||
interfaces::Chain &chain, | Processor::MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain, | ||||
CConnman *connman, | CConnman *connman, ChainstateManager &chainman, | ||||
CScheduler &scheduler, | CScheduler &scheduler, bilingual_str &error) { | ||||
bilingual_str &error) { | |||||
std::unique_ptr<PeerData> peerData; | std::unique_ptr<PeerData> peerData; | ||||
CKey masterKey; | CKey masterKey; | ||||
CKey sessionKey; | CKey sessionKey; | ||||
if (argsman.IsArgSet("-avasessionkey")) { | if (argsman.IsArgSet("-avasessionkey")) { | ||||
sessionKey = DecodeSecret(argsman.GetArg("-avasessionkey", "")); | sessionKey = DecodeSecret(argsman.GetArg("-avasessionkey", "")); | ||||
if (!sessionKey.IsValid()) { | if (!sessionKey.IsValid()) { | ||||
error = _("The avalanche session key is invalid."); | error = _("The avalanche session key is invalid."); | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | if (staleVoteFactor > std::numeric_limits<uint32_t>::max()) { | ||||
error = strprintf(_("The avalanche stale vote factor must be less than " | error = strprintf(_("The avalanche stale vote factor must be less than " | ||||
"or equal to %d"), | "or equal to %d"), | ||||
std::numeric_limits<uint32_t>::max()); | std::numeric_limits<uint32_t>::max()); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
// We can't use std::make_unique with a private constructor | // We can't use std::make_unique with a private constructor | ||||
return std::unique_ptr<Processor>(new Processor( | return std::unique_ptr<Processor>(new Processor( | ||||
argsman, chain, connman, scheduler, std::move(peerData), | argsman, chain, connman, chainman, scheduler, std::move(peerData), | ||||
std::move(sessionKey), Proof::amountToScore(minQuorumStake), | std::move(sessionKey), Proof::amountToScore(minQuorumStake), | ||||
minQuorumConnectedStakeRatio, minAvaproofsNodeCount, staleVoteThreshold, | minQuorumConnectedStakeRatio, minAvaproofsNodeCount, staleVoteThreshold, | ||||
staleVoteFactor)); | staleVoteFactor)); | ||||
} | } | ||||
bool Processor::addBlockToReconcile(const CBlockIndex *pindex) { | bool Processor::addBlockToReconcile(const CBlockIndex *pindex) { | ||||
if (!pindex) { | if (!pindex) { | ||||
// isWorthPolling expects this to be non-null, so bail early. | // isWorthPolling expects this to be non-null, so bail early. | ||||
return false; | return false; | ||||
} | } | ||||
bool isAccepted; | bool isAccepted; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (!isWorthPolling(pindex)) { | if (!isWorthPolling(pindex)) { | ||||
// There is no point polling this block. | // There is no point polling this block. | ||||
return false; | return false; | ||||
} | } | ||||
isAccepted = ::ChainActive().Contains(pindex); | isAccepted = chainman.ActiveChain().Contains(pindex); | ||||
} | } | ||||
return blockVoteRecords.getWriteView() | return blockVoteRecords.getWriteView() | ||||
->insert(std::make_pair(pindex, VoteRecord(isAccepted))) | ->insert(std::make_pair(pindex, VoteRecord(isAccepted))) | ||||
.second; | .second; | ||||
} | } | ||||
bool Processor::addProofToReconcile(const ProofRef &proof) { | bool Processor::addProofToReconcile(const ProofRef &proof) { | ||||
▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Lines | bool Processor::registerVotes(NodeId nodeid, const Response &response, | ||||
// At this stage we are certain that invs[i] matches votes[i], so we can use | // At this stage we are certain that invs[i] matches votes[i], so we can use | ||||
// the inv type to retrieve what is being voted on. | // the inv type to retrieve what is being voted on. | ||||
for (size_t i = 0; i < size; i++) { | for (size_t i = 0; i < size; i++) { | ||||
if (invs[i].IsMsgBlk()) { | if (invs[i].IsMsgBlk()) { | ||||
CBlockIndex *pindex; | CBlockIndex *pindex; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pindex = g_chainman.m_blockman.LookupBlockIndex( | pindex = chainman.m_blockman.LookupBlockIndex( | ||||
BlockHash(votes[i].GetHash())); | BlockHash(votes[i].GetHash())); | ||||
if (!pindex) { | if (!pindex) { | ||||
// This should not happen, but just in case... | // This should not happen, but just in case... | ||||
continue; | continue; | ||||
} | } | ||||
if (!isWorthPolling(pindex)) { | if (!isWorthPolling(pindex)) { | ||||
// There is no point polling this block. | // There is no point polling this block. | ||||
▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | return eventLoop.startEventLoop( | ||||
scheduler, [this]() { this->runEventLoop(); }, AVALANCHE_TIME_STEP); | scheduler, [this]() { this->runEventLoop(); }, AVALANCHE_TIME_STEP); | ||||
} | } | ||||
bool Processor::stopEventLoop() { | bool Processor::stopEventLoop() { | ||||
return eventLoop.stopEventLoop(); | return eventLoop.stopEventLoop(); | ||||
} | } | ||||
void Processor::avaproofsSent(NodeId nodeid) { | void Processor::avaproofsSent(NodeId nodeid) { | ||||
if (::ChainstateActive().IsInitialBlockDownload()) { | if (chainman.ActiveChainstate().IsInitialBlockDownload()) { | ||||
// Before IBD is complete there is no way to make sure a proof is valid | // Before IBD is complete there is no way to make sure a proof is valid | ||||
// or not, e.g. it can be spent in a block we don't know yet. In order | // or not, e.g. it can be spent in a block we don't know yet. In order | ||||
// to increase confidence that our proof set is similar to other nodes | // to increase confidence that our proof set is similar to other nodes | ||||
// on the network, the messages received during IBD are not accounted. | // on the network, the messages received during IBD are not accounted. | ||||
return; | return; | ||||
} | } | ||||
LOCK(cs_peerManager); | LOCK(cs_peerManager); | ||||
if (peerManager->latchAvaproofsSent(nodeid)) { | if (peerManager->latchAvaproofsSent(nodeid)) { | ||||
avaproofsNodeCounter++; | avaproofsNodeCounter++; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Returns a bool indicating whether we have a usable Avalanche quorum enabling | * Returns a bool indicating whether we have a usable Avalanche quorum enabling | ||||
* us to take decisions based on polls. | * us to take decisions based on polls. | ||||
*/ | */ | ||||
bool Processor::isQuorumEstablished() { | bool Processor::isQuorumEstablished() { | ||||
if (quorumIsEstablished) { | if (quorumIsEstablished) { | ||||
return true; | return true; | ||||
} | } | ||||
// Don't do Avalanche while node is IBD'ing | // Don't do Avalanche while node is IBD'ing | ||||
if (::ChainstateActive().IsInitialBlockDownload()) { | if (chainman.ActiveChainstate().IsInitialBlockDownload()) { | ||||
return false; | return false; | ||||
} | } | ||||
if (avaproofsNodeCounter < minAvaproofsNodeCount) { | if (avaproofsNodeCounter < minAvaproofsNodeCount) { | ||||
return false; | return false; | ||||
} | } | ||||
auto localProof = getLocalProof(); | auto localProof = getLocalProof(); | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | auto clearInflightRequest = [&](auto &voteRecords, const auto &voteItem, | ||||
return true; | return true; | ||||
}; | }; | ||||
// In flight request accounting. | // In flight request accounting. | ||||
for (const auto &p : timedout_items) { | for (const auto &p : timedout_items) { | ||||
const CInv &inv = p.first; | const CInv &inv = p.first; | ||||
if (inv.IsMsgBlk()) { | if (inv.IsMsgBlk()) { | ||||
const CBlockIndex *pindex = WITH_LOCK( | const CBlockIndex *pindex = | ||||
cs_main, return g_chainman.m_blockman.LookupBlockIndex( | WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex( | ||||
BlockHash(inv.hash))); | BlockHash(inv.hash))); | ||||
if (!clearInflightRequest(blockVoteRecords, pindex, p.second)) { | if (!clearInflightRequest(blockVoteRecords, pindex, p.second)) { | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
if (inv.IsMsgProof()) { | if (inv.IsMsgProof()) { | ||||
const ProofRef proof = | const ProofRef proof = | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
bool Processor::isWorthPolling(const CBlockIndex *pindex) const { | bool Processor::isWorthPolling(const CBlockIndex *pindex) const { | ||||
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; | ||||
} | } | ||||
if (::ChainstateActive().IsBlockFinalized(pindex)) { | if (chainman.ActiveChainstate().IsBlockFinalized(pindex)) { | ||||
// There is no point polling finalized block. | // There is no point polling finalized block. | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool Processor::isWorthPolling(const ProofRef &proof) const { | bool Processor::isWorthPolling(const ProofRef &proof) const { | ||||
Show All 17 Lines |