Masternode sync improvements:

- add simple helpers for few more sync states (use them where appropriate instead of old code + rpc output)
- use new helpers to avoid meaningless message processing
- actually fail if sync shouldn't continue due to lack of info, make sure Reset is used to quit failed state
This commit is contained in:
UdjinM6 2016-08-28 23:25:09 +03:00
parent 7b10f9aaa6
commit da406e3d23
10 changed files with 60 additions and 30 deletions

View File

@ -2313,7 +2313,7 @@ void CDarksendPool::UpdatedBlockTip(const CBlockIndex *pindex)
pCurrentBlockIndex = pindex;
LogPrint("privatesend", "CDarksendPool::UpdatedBlockTip -- pCurrentBlockIndex->nHeight: %d\n", pCurrentBlockIndex->nHeight);
if(!fLiteMode && masternodeSync.GetAssetID() > MASTERNODE_SYNC_LIST) {
if(!fLiteMode && masternodeSync.IsMasternodeListSynced()) {
NewBlock();
}
}

View File

@ -281,6 +281,9 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
// A NEW GOVERNANCE OBJECT VOTE HAS ARRIVED
else if (strCommand == NetMsgType::MNGOVERNANCEOBJECTVOTE)
{
// Ignore such messages until masternode list is synced
if(!masternodeSync.IsMasternodeListSynced()) return;
CGovernanceVote vote;
vRecv >> vote;
vote.fValid = true;
@ -551,13 +554,12 @@ struct sortProposalsByVotes {
void CGovernanceManager::NewBlock()
{
// IF WE'RE NOT SYNCED, EXIT
if(!masternodeSync.IsSynced()) return;
TRY_LOCK(cs, fBudgetNewBlock);
if(!fBudgetNewBlock || !pCurrentBlockIndex) return;
// IF WE'RE NOT SYNCED, EXIT
if(!masternodeSync.IsSynced()) return;
// CHECK OBJECTS WE'VE ASKED FOR, REMOVE OLD ENTRIES
std::map<uint256, int64_t>::iterator it = mapAskedForGovernanceObject.begin();
@ -1065,7 +1067,7 @@ void CGovernanceManager::UpdatedBlockTip(const CBlockIndex *pindex)
// TO REPROCESS OBJECTS WE SHOULD BE SYNCED
if(!fLiteMode && masternodeSync.GetAssetID() > MASTERNODE_SYNC_LIST)
if(!fLiteMode && masternodeSync.IsSynced())
NewBlock();
}

View File

@ -47,7 +47,9 @@ void ProcessMessageInstantSend(CNode* pfrom, std::string& strCommand, CDataStrea
{
if(fLiteMode) return; // disable all Dash specific functionality
if(!sporkManager.IsSporkActive(SPORK_2_INSTANTX)) return;
if(!masternodeSync.IsBlockchainSynced()) return;
// Ignore any InstantSend messages until masternode list is synced
if(!masternodeSync.IsMasternodeListSynced()) return;
if (strCommand == NetMsgType::IX)
{

View File

@ -260,14 +260,16 @@ int CMasternodePayments::GetMinMasternodePaymentsProto() {
void CMasternodePayments::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
if(!masternodeSync.IsBlockchainSynced()) return;
if(fLiteMode) return; //disable all Darksend/Masternode related functionality
// Ignore any payments messages until masternode list is synced
if(!masternodeSync.IsMasternodeListSynced()) return;
if(fLiteMode) return; // disable all Dash specific functionality
if (strCommand == NetMsgType::MNWINNERSSYNC) { //Masternode Payments Request Sync
// ignore such request until we are fully synced
// Ignore such requests until we are fully synced.
// We could start processing this after masternode list is synced
// but this is a heavy one so it's better to finish sync first.
if (!masternodeSync.IsSynced()) return;
int nCountNeeded;
@ -294,9 +296,6 @@ void CMasternodePayments::ProcessMessage(CNode* pfrom, std::string& strCommand,
if(!pCurrentBlockIndex) return;
// can't really verify it until masternode list is synced, reject it for now
if (masternodeSync.GetAssetID() < MASTERNODE_SYNC_MNW) return;
if(mapMasternodePayeeVotes.count(winner.GetHash())) {
LogPrint("mnpayments", "MNWINNER -- Already seen: hash=%s, nHeight=%d\n", winner.GetHash().ToString(), pCurrentBlockIndex->nHeight);
masternodeSync.AddedMasternodeWinner(winner.GetHash());
@ -549,7 +548,10 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, int nValidationHeight, std:
if(!pmn) {
strError = strprintf("Unknown Masternode: prevout=%s", vinMasternode.prevout.ToStringShort());
// Only ask if we are already synced and still have no idea about that Masternode
if (masternodeSync.IsSynced()) mnodeman.AskForMN(pnode, vinMasternode);
if(masternodeSync.IsSynced()) {
mnodeman.AskForMN(pnode, vinMasternode);
}
return false;
}
@ -581,6 +583,11 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
// DETERMINE IF WE SHOULD BE VOTING FOR THE NEXT PAYEE
if(!fMasterNode) return false;
// We have little chances to pick the right winner if we winners list is out of sync
// but we have no choice, so we'll try. However it doesn't make sense to even try to do so
// if we have not enough data about masternodes.
if(!masternodeSync.IsMasternodeListSynced()) return false;
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 101, MIN_MNW_PEER_PROTO_VERSION);
@ -760,7 +767,7 @@ void CMasternodePayments::UpdatedBlockTip(const CBlockIndex *pindex)
pCurrentBlockIndex = pindex;
LogPrint("mnpayments", "pCurrentBlockIndex->nHeight: %d\n", pCurrentBlockIndex->nHeight);
if (!fLiteMode && masternodeSync.GetAssetID() > MASTERNODE_SYNC_LIST) {
if (!fLiteMode && masternodeSync.IsMasternodeListSynced()) {
ProcessBlock(pindex->nHeight + 10);
}
}

View File

@ -109,8 +109,10 @@ void CMasternodeSync::SwitchToNextAsset()
{
switch(nRequestedMasternodeAssets)
{
case(MASTERNODE_SYNC_FAILED):
throw std::runtime_error("Can't switch to next asset from failed, should use Reset() first!");
break;
case(MASTERNODE_SYNC_INITIAL):
case(MASTERNODE_SYNC_FAILED): // should never be used here actually, use Reset() instead
ClearFulfilledRequest();
nRequestedMasternodeAssets = MASTERNODE_SYNC_SPORKS;
break;
@ -159,9 +161,9 @@ void CMasternodeSync::ProcessMessage(CNode* pfrom, std::string& strCommand, CDat
int nCount;
vRecv >> nItemID >> nCount;
if(nRequestedMasternodeAssets >= MASTERNODE_SYNC_FINISHED) return;
//do not care about stats if sync process finished or failed
if(IsSynced() || IsFailed()) return;
//this means we will receive no further communication
switch(nItemID)
{
case(MASTERNODE_SYNC_LIST):
@ -229,8 +231,9 @@ void CMasternodeSync::ProcessTick()
//try syncing again
if(IsFailed()) {
if(nTimeLastFailure + (1*60) < GetTime()) // 1 minute cooldown after failed sync
if(nTimeLastFailure + (1*60) < GetTime()) { // 1 minute cooldown after failed sync
Reset();
}
return;
}
}
@ -247,7 +250,9 @@ void CMasternodeSync::ProcessTick()
TRY_LOCK(cs_vNodes, lockRecv);
if(!lockRecv) return;
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) SwitchToNextAsset();
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) {
SwitchToNextAsset();
}
BOOST_FOREACH(CNode* pnode, vNodes)
{
@ -295,6 +300,9 @@ void CMasternodeSync::ProcessTick()
LogPrintf("CMasternodeSync::Process -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets);
if (nRequestedMasternodeAttempt == 0) {
LogPrintf("CMasternodeSync::Process -- WARNING: failed to sync %s\n", GetAssetName());
// there is no way we can continue without masternode list, fail here and try later
Fail();
return;
}
SwitchToNextAsset();
return;
@ -333,6 +341,9 @@ void CMasternodeSync::ProcessTick()
LogPrintf("CMasternodeSync::Process -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets);
if (nRequestedMasternodeAttempt == 0) {
LogPrintf("CMasternodeSync::Process -- WARNING: failed to sync %s\n", GetAssetName());
// probably not a good idea to proceed without winner list
Fail();
return;
}
SwitchToNextAsset();
return;

View File

@ -11,6 +11,7 @@
class CMasternodeSync;
static const int MASTERNODE_SYNC_FAILED = -1;
static const int MASTERNODE_SYNC_INITIAL = 0;
static const int MASTERNODE_SYNC_SPORKS = 1;
static const int MASTERNODE_SYNC_LIST = 2;
@ -18,7 +19,6 @@ static const int MASTERNODE_SYNC_MNW = 3;
static const int MASTERNODE_SYNC_GOVERNANCE = 4;
static const int MASTERNODE_SYNC_GOVOBJ = 10;
static const int MASTERNODE_SYNC_GOVERNANCE_FIN = 11;
static const int MASTERNODE_SYNC_FAILED = 998;
static const int MASTERNODE_SYNC_FINISHED = 999;
static const int MASTERNODE_SYNC_TIMEOUT_SECONDS = 30; // our blocks are 2.5 minutes so 30 seconds should be fine
@ -80,8 +80,10 @@ public:
void AddedBudgetItem(uint256 hash);
bool IsFailed() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FAILED; }
bool IsSynced() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FINISHED; }
bool IsBlockchainSynced();
bool IsMasternodeListSynced() { return nRequestedMasternodeAssets > MASTERNODE_SYNC_LIST; }
bool IsWinnersListSynced() { return nRequestedMasternodeAssets > MASTERNODE_SYNC_MNW; }
bool IsSynced() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FINISHED; }
int GetAssetID() { return nRequestedMasternodeAssets; }
int GetAttempt() { return nRequestedMasternodeAttempt; }

View File

@ -568,9 +568,12 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
} else {
if(nDos > 0) Misbehaving(pfrom->GetId(), nDos);
}
}
else if (strCommand == NetMsgType::MNPING) { //Masternode Ping
} else if (strCommand == NetMsgType::MNPING) { //Masternode Ping
// ignore masternode pings until masternode list is synced
if (!masternodeSync.IsMasternodeListSynced()) return;
CMasternodePing mnp;
vRecv >> mnp;
@ -600,7 +603,9 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
} else if (strCommand == NetMsgType::DSEG) { //Get Masternode list or specific entry
// ignore such request until we are fully synced
// Ignore such requests until we are fully synced.
// We could start processing this after masternode list is synced
// but this is a heavy one so it's better to finish sync first.
if (!masternodeSync.IsSynced()) return;
CTxIn vin;

View File

@ -363,7 +363,7 @@ void MasternodeList::on_startAllButton_clicked()
void MasternodeList::on_startMissingButton_clicked()
{
if(masternodeSync.GetAssetID() <= MASTERNODE_SYNC_LIST || masternodeSync.IsFailed()) {
if(!masternodeSync.IsMasternodeListSynced()) {
QMessageBox::critical(this, tr("Command is not available right now"),
tr("You can't use this command until masternode list is synced"));
return;

View File

@ -319,9 +319,8 @@ UniValue masternode(const UniValue& params, bool fHelp)
}
}
if((strCommand == "start-missing" || strCommand == "start-disabled") &&
(masternodeSync.GetAssetID() <= MASTERNODE_SYNC_LIST || masternodeSync.IsFailed())) {
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "You can't use this command until masternode list is synced");
if((strCommand == "start-missing" || strCommand == "start-disabled") && !masternodeSync.IsMasternodeListSynced()) {
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "You can't use this command until masternode list is synced");
}
int successful = 0;

View File

@ -155,6 +155,8 @@ UniValue mnsync(const UniValue& params, bool fHelp)
objStatus.push_back(Pair("AssetName", masternodeSync.GetAssetName()));
objStatus.push_back(Pair("Attempt", masternodeSync.GetAttempt()));
objStatus.push_back(Pair("IsBlockchainSynced", masternodeSync.IsBlockchainSynced()));
objStatus.push_back(Pair("IsMasternodeListSynced", masternodeSync.IsMasternodeListSynced()));
objStatus.push_back(Pair("IsWinnersListSynced", masternodeSync.IsWinnersListSynced()));
objStatus.push_back(Pair("IsSynced", masternodeSync.IsSynced()));
objStatus.push_back(Pair("IsFailed", masternodeSync.IsFailed()));
return objStatus;