From 105713c10adf7148c2a69427afe0b78463e7b16f Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 9 Aug 2017 19:07:03 +0300 Subject: [PATCH] Sync overhaul (#1564) * Change sync process: - IsBlockchainSynced(): drop CheckNodeHeight() and all complicated code, use fInitialDownload in UpdatedBlockTip() to switch initial states - ProcessTick(): detect sleep mode like it was in IsBlockchainSynced(), not by number of masternodes * Changes for sync in governance: - do not keep sync alive on ConfirmInventoryRequest() - skip some governance actions until we are synced to some level * do not run CMasternodeMan::UpdateLastPaid() until winners list is synced * start syncing mn list on the same node right after requesting sporks * replace nTimeLast with the unified nTimeLastBumped, bump on UpdatedBlockTip * fix comments and LogPrintf-s * remove excessive MASTERNODE_SYNC_IBD * a bit more descriptive BumpAssetLastTime in few cases --- src/dsnotificationinterface.cpp | 2 +- src/governance.cpp | 12 +- src/init.cpp | 2 +- src/masternode-payments.cpp | 2 +- src/masternode-sync.cpp | 238 ++++++++------------------------ src/masternode-sync.h | 19 +-- src/masternode.cpp | 4 +- src/masternodeman.cpp | 18 ++- src/rpc/misc.cpp | 1 + src/validation.cpp | 3 - 10 files changed, 85 insertions(+), 216 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 3063b7875..38123ee3b 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -25,7 +25,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con instantsend.UpdatedBlockTip(pindexNew); mnpayments.UpdatedBlockTip(pindexNew); governance.UpdatedBlockTip(pindexNew); - masternodeSync.UpdatedBlockTip(pindexNew); + masternodeSync.UpdatedBlockTip(pindexNew, fInitialDownload); } void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlock *pblock) diff --git a/src/governance.cpp b/src/governance.cpp index eb0e37260..cef9ab4c4 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -263,7 +263,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C CGovernanceException exception; if(ProcessVote(pfrom, vote, exception)) { LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- %s new\n", strHash); - masternodeSync.AddedGovernanceItem(); + masternodeSync.BumpAssetLastTime("MNGOVERNANCEOBJECTVOTE"); vote.Relay(); } else { @@ -384,7 +384,7 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CNode* p // Update the rate buffer MasternodeRateCheck(govobj, UPDATE_TRUE); - masternodeSync.AddedGovernanceItem(); + masternodeSync.BumpAssetLastTime("CGovernanceManager::AddGovernanceObject"); // WE MIGHT HAVE PENDING/ORPHAN VOTES FOR THIS OBJECT @@ -704,6 +704,9 @@ void CGovernanceManager::DoMaintenance() bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv) { + // do not request objects until it's time to sync + if(!masternodeSync.IsWinnersListSynced()) return false; + LOCK(cs); LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest inv = %s\n", inv.ToString()); @@ -750,9 +753,6 @@ bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv) LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest added inv to requested set\n"); } - // Keep sync alive - masternodeSync.AddedGovernanceItem(); - LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest reached end, returning true\n"); return true; } @@ -1073,6 +1073,8 @@ void CGovernanceManager::CheckMasternodeOrphanObjects() void CGovernanceManager::CheckPostponedObjects() { + if(!masternodeSync.IsSynced()) return; + LOCK2(cs_main, cs); // Check postponed proposals diff --git a/src/init.cpp b/src/init.cpp index 62cefbbc8..7088c5998 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1971,7 +1971,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) mnodeman.UpdatedBlockTip(chainActive.Tip()); privateSendClient.UpdatedBlockTip(chainActive.Tip()); mnpayments.UpdatedBlockTip(chainActive.Tip()); - masternodeSync.UpdatedBlockTip(chainActive.Tip()); + masternodeSync.UpdatedBlockTip(chainActive.Tip(), IsInitialBlockDownload()); governance.UpdatedBlockTip(chainActive.Tip()); // ********************************************************* Step 11d: start dash-ps- threads diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index a61bb8ed5..918009fc1 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -410,7 +410,7 @@ void CMasternodePayments::ProcessMessage(CNode* pfrom, std::string& strCommand, if(AddPaymentVote(vote)){ vote.Relay(); - masternodeSync.AddedPaymentVote(); + masternodeSync.BumpAssetLastTime("MASTERNODEPAYMENTVOTE"); } } } diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index 903bf877a..1b325e834 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -17,112 +17,6 @@ class CMasternodeSync; CMasternodeSync masternodeSync; -bool CMasternodeSync::CheckNodeHeight(CNode* pnode, bool fDisconnectStuckNodes) -{ - CNodeStateStats stats; - if(!GetNodeStateStats(pnode->id, stats) || stats.nCommonHeight == -1 || stats.nSyncHeight == -1) return false; // not enough info about this peer - - // Check blocks and headers, allow a small error margin of 1 block - if(pCurrentBlockIndex->nHeight - 1 > stats.nCommonHeight) { - // This peer probably stuck, don't sync any additional data from it - if(fDisconnectStuckNodes) { - // Disconnect to free this connection slot for another peer. - pnode->fDisconnect = true; - LogPrintf("CMasternodeSync::CheckNodeHeight -- disconnecting from stuck peer, nHeight=%d, nCommonHeight=%d, peer=%d\n", - pCurrentBlockIndex->nHeight, stats.nCommonHeight, pnode->id); - } else { - LogPrintf("CMasternodeSync::CheckNodeHeight -- skipping stuck peer, nHeight=%d, nCommonHeight=%d, peer=%d\n", - pCurrentBlockIndex->nHeight, stats.nCommonHeight, pnode->id); - } - return false; - } - else if(pCurrentBlockIndex->nHeight < stats.nSyncHeight - 1) { - // This peer announced more headers than we have blocks currently - LogPrintf("CMasternodeSync::CheckNodeHeight -- skipping peer, who announced more headers than we have blocks currently, nHeight=%d, nSyncHeight=%d, peer=%d\n", - pCurrentBlockIndex->nHeight, stats.nSyncHeight, pnode->id); - return false; - } - - return true; -} - -bool CMasternodeSync::IsBlockchainSynced(bool fBlockAccepted) -{ - static bool fBlockchainSynced = false; - static int nSkipped = 0; - static bool fFirstBlockAccepted = false; - - if(!pCurrentBlockIndex || !pindexBestHeader || fImporting || fReindex) return false; - - static int64_t nTimeLastProcess = GetTime(); - - // if the last call to this function was more than 60 minutes ago (client was in sleep mode) reset the sync process - if(GetTime() - nTimeLastProcess > 60*60) { - Reset(); - fBlockchainSynced = false; - } - - if(fBlockAccepted) { - // this should be only triggered while we are still syncing - if(!IsSynced()) { - // we are trying to download smth, reset blockchain sync status - if(fDebug) LogPrintf("CMasternodeSync::IsBlockchainSynced -- reset\n"); - fFirstBlockAccepted = true; - fBlockchainSynced = false; - nTimeLastProcess = GetTime(); - return false; - } - } else { - // skip if we already checked less than 1 tick ago - if(GetTime() - nTimeLastProcess < MASTERNODE_SYNC_TICK_SECONDS) { - nSkipped++; - return fBlockchainSynced; - } - } - - if(fDebug) LogPrintf("CMasternodeSync::IsBlockchainSynced -- state before check: %ssynced, skipped %d times\n", fBlockchainSynced ? "" : "not ", nSkipped); - - nTimeLastProcess = GetTime(); - nSkipped = 0; - - if(fBlockchainSynced) return true; - - if(fCheckpointsEnabled && pCurrentBlockIndex->nHeight < Checkpoints::GetTotalBlocksEstimate(Params().Checkpoints())) - return false; - - std::vector vNodesCopy = g_connman->CopyNodeVector(); - - // We have enough peers and assume most of them are synced - if(vNodesCopy.size() >= MASTERNODE_SYNC_ENOUGH_PEERS) { - // Check to see how many of our peers are (almost) at the same height as we are - int nNodesAtSameHeight = 0; - BOOST_FOREACH(CNode* pnode, vNodesCopy) - { - // Make sure this peer is presumably at the same height - if(!CheckNodeHeight(pnode)) continue; - nNodesAtSameHeight++; - // if we have decent number of such peers, most likely we are synced now - if(nNodesAtSameHeight >= MASTERNODE_SYNC_ENOUGH_PEERS) { - LogPrintf("CMasternodeSync::IsBlockchainSynced -- found enough peers on the same height as we are, done\n"); - fBlockchainSynced = true; - g_connman->ReleaseNodeVector(vNodesCopy); - return true; - } - } - } - g_connman->ReleaseNodeVector(vNodesCopy); - - // wait for at least one new block to be accepted - if(!fFirstBlockAccepted) return false; - - // same as !IsInitialBlockDownload() but no cs_main needed here - int64_t nMaxBlockTime = std::max(pCurrentBlockIndex->GetBlockTime(), pindexBestHeader->GetBlockTime()); - fBlockchainSynced = pindexBestHeader->nHeight - pCurrentBlockIndex->nHeight < 24 * 6 && - GetTime() - nMaxBlockTime < Params().MaxTipAge(); - - return fBlockchainSynced; -} - void CMasternodeSync::Fail() { nTimeLastFailure = GetTime(); @@ -134,18 +28,22 @@ void CMasternodeSync::Reset() nRequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL; nRequestedMasternodeAttempt = 0; nTimeAssetSyncStarted = GetTime(); - nTimeLastMasternodeList = GetTime(); - nTimeLastPaymentVote = GetTime(); - nTimeLastGovernanceItem = GetTime(); + nTimeLastBumped = 0; nTimeLastFailure = 0; } +void CMasternodeSync::BumpAssetLastTime(std::string strFuncName) +{ + if(IsSynced() || IsFailed()) return; + nTimeLastBumped = GetTime(); + if(fDebug) LogPrintf("CMasternodeSync::BumpAssetLastTime -- %s\n", strFuncName); +} + std::string CMasternodeSync::GetAssetName() { switch(nRequestedMasternodeAssets) { case(MASTERNODE_SYNC_INITIAL): return "MASTERNODE_SYNC_INITIAL"; - case(MASTERNODE_SYNC_SPORKS): return "MASTERNODE_SYNC_SPORKS"; case(MASTERNODE_SYNC_LIST): return "MASTERNODE_SYNC_LIST"; case(MASTERNODE_SYNC_MNW): return "MASTERNODE_SYNC_MNW"; case(MASTERNODE_SYNC_GOVERNANCE): return "MASTERNODE_SYNC_GOVERNANCE"; @@ -164,29 +62,21 @@ void CMasternodeSync::SwitchToNextAsset() break; case(MASTERNODE_SYNC_INITIAL): ClearFulfilledRequests(); - nRequestedMasternodeAssets = MASTERNODE_SYNC_SPORKS; - LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); - break; - case(MASTERNODE_SYNC_SPORKS): - LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); - nTimeLastMasternodeList = GetTime(); nRequestedMasternodeAssets = MASTERNODE_SYNC_LIST; LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); break; case(MASTERNODE_SYNC_LIST): - LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); - nTimeLastPaymentVote = GetTime(); + LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); nRequestedMasternodeAssets = MASTERNODE_SYNC_MNW; LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); break; case(MASTERNODE_SYNC_MNW): - LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); - nTimeLastGovernanceItem = GetTime(); + LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); nRequestedMasternodeAssets = MASTERNODE_SYNC_GOVERNANCE; LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); break; case(MASTERNODE_SYNC_GOVERNANCE): - LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); + LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED; uiInterface.NotifyAdditionalDataSyncProgressChanged(1); //try to activate our masternode if possible @@ -205,13 +95,13 @@ void CMasternodeSync::SwitchToNextAsset() } nRequestedMasternodeAttempt = 0; nTimeAssetSyncStarted = GetTime(); + BumpAssetLastTime("CMasternodeSync::SwitchToNextAsset"); } std::string CMasternodeSync::GetSyncStatus() { switch (masternodeSync.nRequestedMasternodeAssets) { case MASTERNODE_SYNC_INITIAL: return _("Synchronization pending..."); - case MASTERNODE_SYNC_SPORKS: return _("Synchronizing sporks..."); case MASTERNODE_SYNC_LIST: return _("Synchronizing masternodes..."); case MASTERNODE_SYNC_MNW: return _("Synchronizing masternode payments..."); case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects..."); @@ -257,59 +147,39 @@ void CMasternodeSync::ProcessTick() if(nTick++ % MASTERNODE_SYNC_TICK_SECONDS != 0) return; if(!pCurrentBlockIndex) return; - //the actual count of masternodes we have currently - int nMnCount = mnodeman.CountMasternodes(); - - if(fDebug) LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nMnCount %d\n", nTick, nMnCount); - - // RESET SYNCING INCASE OF FAILURE - { - if(IsSynced()) { - /* - Resync if we lost all masternodes from sleep/wake or failed to sync originally - */ - if(nMnCount == 0) { - LogPrintf("CMasternodeSync::ProcessTick -- WARNING: not enough data, restarting sync\n"); - Reset(); - } else { - std::vector vNodesCopy = g_connman->CopyNodeVector(); - governance.RequestGovernanceObjectVotes(vNodesCopy); - g_connman->ReleaseNodeVector(vNodesCopy); - return; - } - } - - //try syncing again - if(IsFailed()) { - if(nTimeLastFailure + (1*60) < GetTime()) { // 1 minute cooldown after failed sync - Reset(); - } - return; - } + // reset the sync process if the last call to this function was more than 60 minutes ago (client was in sleep mode) + static int64_t nTimeLastProcess = GetTime(); + if(GetTime() - nTimeLastProcess > 60*60) { + LogPrintf("CMasternodeSync::HasSyncFailures -- WARNING: no actions for too long, restarting sync...\n"); + Reset(); + SwitchToNextAsset(); + return; } + nTimeLastProcess = GetTime(); - // INITIAL SYNC SETUP / LOG REPORTING - double nSyncProgress = double(nRequestedMasternodeAttempt + (nRequestedMasternodeAssets - 1) * 8) / (8*4); - LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nRequestedMasternodeAttempt %d nSyncProgress %f\n", nTick, nRequestedMasternodeAssets, nRequestedMasternodeAttempt, nSyncProgress); - uiInterface.NotifyAdditionalDataSyncProgressChanged(nSyncProgress); - - // sporks synced but blockchain is not, wait until we're almost at a recent block to continue - if(Params().NetworkIDString() != CBaseChainParams::REGTEST && - !IsBlockchainSynced() && nRequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS) - { - LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nRequestedMasternodeAttempt %d -- blockchain is not synced yet\n", nTick, nRequestedMasternodeAssets, nRequestedMasternodeAttempt); - nTimeLastMasternodeList = GetTime(); - nTimeLastPaymentVote = GetTime(); - nTimeLastGovernanceItem = GetTime(); + // reset sync status in case of any other sync failure + if(IsFailed()) { + if(nTimeLastFailure + (1*60) < GetTime()) { // 1 minute cooldown after failed sync + LogPrintf("CMasternodeSync::HasSyncFailures -- WARNING: failed to sync, trying again...\n"); + Reset(); + SwitchToNextAsset(); + } return; } - if(nRequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL || - (nRequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS && IsBlockchainSynced())) - { - SwitchToNextAsset(); + // gradually request the rest of the votes after sync finished + if(IsSynced()) { + std::vector vNodesCopy = g_connman->CopyNodeVector(); + governance.RequestGovernanceObjectVotes(vNodesCopy); + g_connman->ReleaseNodeVector(vNodesCopy); + return; } + // Calculate "progress" for LOG reporting / GUI notification + double nSyncProgress = double(nRequestedMasternodeAttempt + (nRequestedMasternodeAssets - 1) * 8) / (8*4); + LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nRequestedMasternodeAttempt %d nSyncProgress %f\n", nTick, nRequestedMasternodeAssets, nRequestedMasternodeAttempt, nSyncProgress); + uiInterface.NotifyAdditionalDataSyncProgressChanged(nSyncProgress); + std::vector vNodesCopy = g_connman->CopyNodeVector(); BOOST_FOREACH(CNode* pnode, vNodesCopy) @@ -349,23 +219,22 @@ void CMasternodeSync::ProcessTick() continue; } - // SPORK : ALWAYS ASK FOR SPORKS AS WE SYNC (we skip this mode now) + // SPORK : ALWAYS ASK FOR SPORKS AS WE SYNC if(!netfulfilledman.HasFulfilledRequest(pnode->addr, "spork-sync")) { - // only request once from each peer + // always get sporks first, only request once from each peer netfulfilledman.AddFulfilledRequest(pnode->addr, "spork-sync"); // get current network sporks g_connman->PushMessageWithVersion(pnode, INIT_PROTO_VERSION, NetMsgType::GETSPORKS); LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- requesting sporks from peer %d\n", nTick, nRequestedMasternodeAssets, pnode->id); - continue; // always get sporks first, switch to the next node without waiting for the next tick } // MNLIST : SYNC MASTERNODE LIST FROM OTHER CONNECTED CLIENTS if(nRequestedMasternodeAssets == MASTERNODE_SYNC_LIST) { - LogPrint("masternode", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastMasternodeList %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastMasternodeList, GetTime(), GetTime() - nTimeLastMasternodeList); + LogPrint("masternode", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped); // check for timeout first - if(GetTime() - nTimeLastMasternodeList > MASTERNODE_SYNC_TIMEOUT_SECONDS) { + if(GetTime() - nTimeLastBumped > MASTERNODE_SYNC_TIMEOUT_SECONDS) { LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets); if (nRequestedMasternodeAttempt == 0) { LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName()); @@ -395,11 +264,11 @@ void CMasternodeSync::ProcessTick() // MNW : SYNC MASTERNODE PAYMENT VOTES FROM OTHER CONNECTED CLIENTS if(nRequestedMasternodeAssets == MASTERNODE_SYNC_MNW) { - LogPrint("mnpayments", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastPaymentVote %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastPaymentVote, GetTime(), GetTime() - nTimeLastPaymentVote); + LogPrint("mnpayments", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped); // check for timeout first - // This might take a lot longer than MASTERNODE_SYNC_TIMEOUT_SECONDS minutes due to new blocks, + // This might take a lot longer than MASTERNODE_SYNC_TIMEOUT_SECONDS due to new blocks, // but that should be OK and it should timeout eventually. - if(GetTime() - nTimeLastPaymentVote > MASTERNODE_SYNC_TIMEOUT_SECONDS) { + if(GetTime() - nTimeLastBumped > MASTERNODE_SYNC_TIMEOUT_SECONDS) { LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets); if (nRequestedMasternodeAttempt == 0) { LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName()); @@ -442,10 +311,10 @@ void CMasternodeSync::ProcessTick() // GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS if(nRequestedMasternodeAssets == MASTERNODE_SYNC_GOVERNANCE) { - LogPrint("gobject", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastGovernanceItem %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastGovernanceItem, GetTime(), GetTime() - nTimeLastGovernanceItem); + LogPrint("gobject", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped); // check for timeout first - if(GetTime() - nTimeLastGovernanceItem > MASTERNODE_SYNC_TIMEOUT_SECONDS) { + if(GetTime() - nTimeLastBumped > MASTERNODE_SYNC_TIMEOUT_SECONDS) { LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets); if(nRequestedMasternodeAttempt == 0) { LogPrintf("CMasternodeSync::ProcessTick -- WARNING: failed to sync %s\n", GetAssetName()); @@ -518,7 +387,16 @@ void CMasternodeSync::SendGovernanceSyncRequest(CNode* pnode) } } -void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindex) +void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload) { - pCurrentBlockIndex = pindex; + pCurrentBlockIndex = pindexNew; + if(fDebug) LogPrintf("CMasternodeSync::UpdatedBlockTip -- pCurrentBlockIndex->nHeight: %d fInitialDownload=%d\n", pCurrentBlockIndex->nHeight, fInitialDownload); + // nothing to do here if we failed to sync previousely, + // just wait till status reset after a cooldown (see ProcessTick) + if(IsFailed()) return; + // switch from MASTERNODE_SYNC_INITIAL to the next "asset" + // the first time we are out of IBD mode (and only the first time) + if(!fInitialDownload && !IsBlockchainSynced()) SwitchToNextAsset(); + // postpone timeout each time new block arrives while we are syncing + if(!IsSynced()) BumpAssetLastTime("CMasternodeSync::UpdatedBlockTip"); } diff --git a/src/masternode-sync.h b/src/masternode-sync.h index 451ef5065..f0c457b87 100644 --- a/src/masternode-sync.h +++ b/src/masternode-sync.h @@ -12,8 +12,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_INITIAL = 0; // sync just started, was reset recently or still in IDB static const int MASTERNODE_SYNC_LIST = 2; static const int MASTERNODE_SYNC_MNW = 3; static const int MASTERNODE_SYNC_GOVERNANCE = 4; @@ -42,38 +41,32 @@ private: // Time when current masternode asset sync started int64_t nTimeAssetSyncStarted; - - // Last time when we received some masternode asset ... - int64_t nTimeLastMasternodeList; - int64_t nTimeLastPaymentVote; - int64_t nTimeLastGovernanceItem; + // ... last bumped + int64_t nTimeLastBumped; // ... or failed int64_t nTimeLastFailure; // Keep track of current block index const CBlockIndex *pCurrentBlockIndex; - bool CheckNodeHeight(CNode* pnode, bool fDisconnectStuckNodes = false); void Fail(); void ClearFulfilledRequests(); public: CMasternodeSync() { Reset(); } - void AddedMasternodeList() { nTimeLastMasternodeList = GetTime(); } - void AddedPaymentVote() { nTimeLastPaymentVote = GetTime(); } - void AddedGovernanceItem() { nTimeLastGovernanceItem = GetTime(); }; void SendGovernanceSyncRequest(CNode* pnode); bool IsFailed() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FAILED; } - bool IsBlockchainSynced(bool fBlockAccepted = false); + bool IsBlockchainSynced() { return nRequestedMasternodeAssets > MASTERNODE_SYNC_INITIAL; } 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; } + void BumpAssetLastTime(std::string strFuncName); int64_t GetAssetStartTime() { return nTimeAssetSyncStarted; } std::string GetAssetName(); std::string GetSyncStatus(); @@ -84,7 +77,7 @@ public: void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); void ProcessTick(); - void UpdatedBlockTip(const CBlockIndex *pindex); + void UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload); }; #endif diff --git a/src/masternode.cpp b/src/masternode.cpp index 6227a9a48..12fddde31 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -627,7 +627,7 @@ bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos) pmn->Check(); Relay(); } - masternodeSync.AddedMasternodeList(); + masternodeSync.BumpAssetLastTime("CMasternodeBroadcast::Update"); } return true; @@ -890,7 +890,7 @@ bool CMasternodePing::CheckAndUpdate(CMasternode* pmn, bool fFromNewBroadcast, i if(!masternodeSync.IsMasternodeListSynced() && !pmn->IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS/2)) { // let's bump sync timeout LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- bumping sync timeout, masternode=%s\n", vin.prevout.ToStringShort()); - masternodeSync.AddedMasternodeList(); + masternodeSync.BumpAssetLastTime("CMasternodePing::CheckAndUpdate"); } // let's store this ping as the last one diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 37c4d7fb2..26e03fe7a 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -1390,14 +1390,13 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb) CMasternode* pmn = Find(mnb.vin); if(pmn == NULL) { - CMasternode mn(mnb); - if(Add(mn)) { - masternodeSync.AddedMasternodeList(); + if(Add(mnb)) { + masternodeSync.BumpAssetLastTime("CMasternodeMan::UpdateMasternodeList - new"); } } else { CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second; if(pmn->UpdateFromNewBroadcast(mnb)) { - masternodeSync.AddedMasternodeList(); + masternodeSync.BumpAssetLastTime("CMasternodeMan::UpdateMasternodeList - seen"); mapSeenMasternodeBroadcast.erase(mnbOld.GetHash()); } } @@ -1420,7 +1419,7 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBr if(GetTime() - mapSeenMasternodeBroadcast[hash].first > MASTERNODE_NEW_START_REQUIRED_SECONDS - MASTERNODE_MIN_MNP_SECONDS * 2) { LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen update\n", mnb.vin.prevout.ToStringShort()); mapSeenMasternodeBroadcast[hash].first = GetTime(); - masternodeSync.AddedMasternodeList(); + masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - seen"); } // did we ask this node for it? if(pfrom && IsMnbRecoveryRequested(hash) && GetTime() < mMnbRecoveryRequests[hash].first) { @@ -1471,7 +1470,7 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBr if(mnb.CheckOutpoint(nDos)) { Add(mnb); - masternodeSync.AddedMasternodeList(); + masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - new"); // if it matches our Masternode privkey... if(fMasterNode && mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode) { mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE; @@ -1500,8 +1499,8 @@ void CMasternodeMan::UpdateLastPaid() { LOCK(cs); - if(fLiteMode) return; - if(!pCurrentBlockIndex) return; + if(fLiteMode || !pCurrentBlockIndex) return; + if(!masternodeSync.IsWinnersListSynced() || vMasternodes.empty()) return; static bool IsFirstRun = true; // Do full scan on first run or if we are not a masternode @@ -1515,8 +1514,7 @@ void CMasternodeMan::UpdateLastPaid() mn.UpdateLastPaid(pCurrentBlockIndex, nMaxBlocksToScanBack); } - // every time is like the first time if winners list is not synced - IsFirstRun = !masternodeSync.IsWinnersListSynced(); + IsFirstRun = false; } bool CMasternodeMan::UpdateLastDsq(const CTxIn& vin) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index a0f9338b9..db077a823 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -173,6 +173,7 @@ UniValue mnsync(const UniValue& params, bool fHelp) if(strMode == "reset") { masternodeSync.Reset(); + masternodeSync.SwitchToNextAsset(); return "success"; } return "failure"; diff --git a/src/validation.cpp b/src/validation.cpp index 5ec957962..39e954715 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -38,7 +38,6 @@ #include "instantx.h" #include "masternode-payments.h" -#include "masternode-sync.h" #include @@ -3456,8 +3455,6 @@ bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool if (!ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed", __func__); - masternodeSync.IsBlockchainSynced(true); - LogPrintf("%s : ACCEPTED\n", __func__); return true; }