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<Asset> 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
This commit is contained in:
UdjinM6 2017-08-09 19:07:03 +03:00 committed by GitHub
parent 42c784dc7a
commit 105713c10a
10 changed files with 85 additions and 216 deletions

View File

@ -25,7 +25,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con
instantsend.UpdatedBlockTip(pindexNew); instantsend.UpdatedBlockTip(pindexNew);
mnpayments.UpdatedBlockTip(pindexNew); mnpayments.UpdatedBlockTip(pindexNew);
governance.UpdatedBlockTip(pindexNew); governance.UpdatedBlockTip(pindexNew);
masternodeSync.UpdatedBlockTip(pindexNew); masternodeSync.UpdatedBlockTip(pindexNew, fInitialDownload);
} }
void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlock *pblock) void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlock *pblock)

View File

@ -263,7 +263,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
CGovernanceException exception; CGovernanceException exception;
if(ProcessVote(pfrom, vote, exception)) { if(ProcessVote(pfrom, vote, exception)) {
LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- %s new\n", strHash); LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- %s new\n", strHash);
masternodeSync.AddedGovernanceItem(); masternodeSync.BumpAssetLastTime("MNGOVERNANCEOBJECTVOTE");
vote.Relay(); vote.Relay();
} }
else { else {
@ -384,7 +384,7 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CNode* p
// Update the rate buffer // Update the rate buffer
MasternodeRateCheck(govobj, UPDATE_TRUE); MasternodeRateCheck(govobj, UPDATE_TRUE);
masternodeSync.AddedGovernanceItem(); masternodeSync.BumpAssetLastTime("CGovernanceManager::AddGovernanceObject");
// WE MIGHT HAVE PENDING/ORPHAN VOTES FOR THIS OBJECT // WE MIGHT HAVE PENDING/ORPHAN VOTES FOR THIS OBJECT
@ -704,6 +704,9 @@ void CGovernanceManager::DoMaintenance()
bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv) bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv)
{ {
// do not request objects until it's time to sync
if(!masternodeSync.IsWinnersListSynced()) return false;
LOCK(cs); LOCK(cs);
LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest inv = %s\n", inv.ToString()); 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"); LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest added inv to requested set\n");
} }
// Keep sync alive
masternodeSync.AddedGovernanceItem();
LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest reached end, returning true\n"); LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest reached end, returning true\n");
return true; return true;
} }
@ -1073,6 +1073,8 @@ void CGovernanceManager::CheckMasternodeOrphanObjects()
void CGovernanceManager::CheckPostponedObjects() void CGovernanceManager::CheckPostponedObjects()
{ {
if(!masternodeSync.IsSynced()) return;
LOCK2(cs_main, cs); LOCK2(cs_main, cs);
// Check postponed proposals // Check postponed proposals

View File

@ -1971,7 +1971,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
mnodeman.UpdatedBlockTip(chainActive.Tip()); mnodeman.UpdatedBlockTip(chainActive.Tip());
privateSendClient.UpdatedBlockTip(chainActive.Tip()); privateSendClient.UpdatedBlockTip(chainActive.Tip());
mnpayments.UpdatedBlockTip(chainActive.Tip()); mnpayments.UpdatedBlockTip(chainActive.Tip());
masternodeSync.UpdatedBlockTip(chainActive.Tip()); masternodeSync.UpdatedBlockTip(chainActive.Tip(), IsInitialBlockDownload());
governance.UpdatedBlockTip(chainActive.Tip()); governance.UpdatedBlockTip(chainActive.Tip());
// ********************************************************* Step 11d: start dash-ps-<smth> threads // ********************************************************* Step 11d: start dash-ps-<smth> threads

View File

@ -410,7 +410,7 @@ void CMasternodePayments::ProcessMessage(CNode* pfrom, std::string& strCommand,
if(AddPaymentVote(vote)){ if(AddPaymentVote(vote)){
vote.Relay(); vote.Relay();
masternodeSync.AddedPaymentVote(); masternodeSync.BumpAssetLastTime("MASTERNODEPAYMENTVOTE");
} }
} }
} }

View File

@ -17,112 +17,6 @@
class CMasternodeSync; class CMasternodeSync;
CMasternodeSync masternodeSync; 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<CNode*> 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() void CMasternodeSync::Fail()
{ {
nTimeLastFailure = GetTime(); nTimeLastFailure = GetTime();
@ -134,18 +28,22 @@ void CMasternodeSync::Reset()
nRequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL; nRequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL;
nRequestedMasternodeAttempt = 0; nRequestedMasternodeAttempt = 0;
nTimeAssetSyncStarted = GetTime(); nTimeAssetSyncStarted = GetTime();
nTimeLastMasternodeList = GetTime(); nTimeLastBumped = 0;
nTimeLastPaymentVote = GetTime();
nTimeLastGovernanceItem = GetTime();
nTimeLastFailure = 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() std::string CMasternodeSync::GetAssetName()
{ {
switch(nRequestedMasternodeAssets) switch(nRequestedMasternodeAssets)
{ {
case(MASTERNODE_SYNC_INITIAL): return "MASTERNODE_SYNC_INITIAL"; 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_LIST): return "MASTERNODE_SYNC_LIST";
case(MASTERNODE_SYNC_MNW): return "MASTERNODE_SYNC_MNW"; case(MASTERNODE_SYNC_MNW): return "MASTERNODE_SYNC_MNW";
case(MASTERNODE_SYNC_GOVERNANCE): return "MASTERNODE_SYNC_GOVERNANCE"; case(MASTERNODE_SYNC_GOVERNANCE): return "MASTERNODE_SYNC_GOVERNANCE";
@ -164,29 +62,21 @@ void CMasternodeSync::SwitchToNextAsset()
break; break;
case(MASTERNODE_SYNC_INITIAL): case(MASTERNODE_SYNC_INITIAL):
ClearFulfilledRequests(); 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; nRequestedMasternodeAssets = MASTERNODE_SYNC_LIST;
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
break; break;
case(MASTERNODE_SYNC_LIST): case(MASTERNODE_SYNC_LIST):
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
nTimeLastPaymentVote = GetTime();
nRequestedMasternodeAssets = MASTERNODE_SYNC_MNW; nRequestedMasternodeAssets = MASTERNODE_SYNC_MNW;
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
break; break;
case(MASTERNODE_SYNC_MNW): case(MASTERNODE_SYNC_MNW):
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
nTimeLastGovernanceItem = GetTime();
nRequestedMasternodeAssets = MASTERNODE_SYNC_GOVERNANCE; nRequestedMasternodeAssets = MASTERNODE_SYNC_GOVERNANCE;
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
break; break;
case(MASTERNODE_SYNC_GOVERNANCE): 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; nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
uiInterface.NotifyAdditionalDataSyncProgressChanged(1); uiInterface.NotifyAdditionalDataSyncProgressChanged(1);
//try to activate our masternode if possible //try to activate our masternode if possible
@ -205,13 +95,13 @@ void CMasternodeSync::SwitchToNextAsset()
} }
nRequestedMasternodeAttempt = 0; nRequestedMasternodeAttempt = 0;
nTimeAssetSyncStarted = GetTime(); nTimeAssetSyncStarted = GetTime();
BumpAssetLastTime("CMasternodeSync::SwitchToNextAsset");
} }
std::string CMasternodeSync::GetSyncStatus() std::string CMasternodeSync::GetSyncStatus()
{ {
switch (masternodeSync.nRequestedMasternodeAssets) { switch (masternodeSync.nRequestedMasternodeAssets) {
case MASTERNODE_SYNC_INITIAL: return _("Synchronization pending..."); case MASTERNODE_SYNC_INITIAL: return _("Synchronization pending...");
case MASTERNODE_SYNC_SPORKS: return _("Synchronizing sporks...");
case MASTERNODE_SYNC_LIST: return _("Synchronizing masternodes..."); case MASTERNODE_SYNC_LIST: return _("Synchronizing masternodes...");
case MASTERNODE_SYNC_MNW: return _("Synchronizing masternode payments..."); case MASTERNODE_SYNC_MNW: return _("Synchronizing masternode payments...");
case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects..."); case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects...");
@ -257,59 +147,39 @@ void CMasternodeSync::ProcessTick()
if(nTick++ % MASTERNODE_SYNC_TICK_SECONDS != 0) return; if(nTick++ % MASTERNODE_SYNC_TICK_SECONDS != 0) return;
if(!pCurrentBlockIndex) return; if(!pCurrentBlockIndex) return;
//the actual count of masternodes we have currently // reset the sync process if the last call to this function was more than 60 minutes ago (client was in sleep mode)
int nMnCount = mnodeman.CountMasternodes(); static int64_t nTimeLastProcess = GetTime();
if(GetTime() - nTimeLastProcess > 60*60) {
if(fDebug) LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nMnCount %d\n", nTick, nMnCount); LogPrintf("CMasternodeSync::HasSyncFailures -- WARNING: no actions for too long, restarting sync...\n");
Reset();
// RESET SYNCING INCASE OF FAILURE SwitchToNextAsset();
{ return;
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<CNode*> 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;
}
} }
nTimeLastProcess = GetTime();
// INITIAL SYNC SETUP / LOG REPORTING // reset sync status in case of any other sync failure
double nSyncProgress = double(nRequestedMasternodeAttempt + (nRequestedMasternodeAssets - 1) * 8) / (8*4); if(IsFailed()) {
LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nRequestedMasternodeAttempt %d nSyncProgress %f\n", nTick, nRequestedMasternodeAssets, nRequestedMasternodeAttempt, nSyncProgress); if(nTimeLastFailure + (1*60) < GetTime()) { // 1 minute cooldown after failed sync
uiInterface.NotifyAdditionalDataSyncProgressChanged(nSyncProgress); LogPrintf("CMasternodeSync::HasSyncFailures -- WARNING: failed to sync, trying again...\n");
Reset();
// sporks synced but blockchain is not, wait until we're almost at a recent block to continue SwitchToNextAsset();
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();
return; return;
} }
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL || // gradually request the rest of the votes after sync finished
(nRequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS && IsBlockchainSynced())) if(IsSynced()) {
{ std::vector<CNode*> vNodesCopy = g_connman->CopyNodeVector();
SwitchToNextAsset(); 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<CNode*> vNodesCopy = g_connman->CopyNodeVector(); std::vector<CNode*> vNodesCopy = g_connman->CopyNodeVector();
BOOST_FOREACH(CNode* pnode, vNodesCopy) BOOST_FOREACH(CNode* pnode, vNodesCopy)
@ -349,23 +219,22 @@ void CMasternodeSync::ProcessTick()
continue; 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")) { 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"); netfulfilledman.AddFulfilledRequest(pnode->addr, "spork-sync");
// get current network sporks // get current network sporks
g_connman->PushMessageWithVersion(pnode, INIT_PROTO_VERSION, NetMsgType::GETSPORKS); 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); 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 // MNLIST : SYNC MASTERNODE LIST FROM OTHER CONNECTED CLIENTS
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_LIST) { 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 // 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); LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets);
if (nRequestedMasternodeAttempt == 0) { if (nRequestedMasternodeAttempt == 0) {
LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName()); 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 // MNW : SYNC MASTERNODE PAYMENT VOTES FROM OTHER CONNECTED CLIENTS
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_MNW) { 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 // 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. // 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); LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets);
if (nRequestedMasternodeAttempt == 0) { if (nRequestedMasternodeAttempt == 0) {
LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName()); LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName());
@ -442,10 +311,10 @@ void CMasternodeSync::ProcessTick()
// GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS // GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_GOVERNANCE) { 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 // 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); LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout\n", nTick, nRequestedMasternodeAssets);
if(nRequestedMasternodeAttempt == 0) { if(nRequestedMasternodeAttempt == 0) {
LogPrintf("CMasternodeSync::ProcessTick -- WARNING: failed to sync %s\n", GetAssetName()); 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");
} }

View File

@ -12,8 +12,7 @@
class CMasternodeSync; class CMasternodeSync;
static const int MASTERNODE_SYNC_FAILED = -1; static const int MASTERNODE_SYNC_FAILED = -1;
static const int MASTERNODE_SYNC_INITIAL = 0; static const int MASTERNODE_SYNC_INITIAL = 0; // sync just started, was reset recently or still in IDB
static const int MASTERNODE_SYNC_SPORKS = 1;
static const int MASTERNODE_SYNC_LIST = 2; static const int MASTERNODE_SYNC_LIST = 2;
static const int MASTERNODE_SYNC_MNW = 3; static const int MASTERNODE_SYNC_MNW = 3;
static const int MASTERNODE_SYNC_GOVERNANCE = 4; static const int MASTERNODE_SYNC_GOVERNANCE = 4;
@ -42,38 +41,32 @@ private:
// Time when current masternode asset sync started // Time when current masternode asset sync started
int64_t nTimeAssetSyncStarted; int64_t nTimeAssetSyncStarted;
// ... last bumped
// Last time when we received some masternode asset ... int64_t nTimeLastBumped;
int64_t nTimeLastMasternodeList;
int64_t nTimeLastPaymentVote;
int64_t nTimeLastGovernanceItem;
// ... or failed // ... or failed
int64_t nTimeLastFailure; int64_t nTimeLastFailure;
// Keep track of current block index // Keep track of current block index
const CBlockIndex *pCurrentBlockIndex; const CBlockIndex *pCurrentBlockIndex;
bool CheckNodeHeight(CNode* pnode, bool fDisconnectStuckNodes = false);
void Fail(); void Fail();
void ClearFulfilledRequests(); void ClearFulfilledRequests();
public: public:
CMasternodeSync() { Reset(); } CMasternodeSync() { Reset(); }
void AddedMasternodeList() { nTimeLastMasternodeList = GetTime(); }
void AddedPaymentVote() { nTimeLastPaymentVote = GetTime(); }
void AddedGovernanceItem() { nTimeLastGovernanceItem = GetTime(); };
void SendGovernanceSyncRequest(CNode* pnode); void SendGovernanceSyncRequest(CNode* pnode);
bool IsFailed() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FAILED; } 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 IsMasternodeListSynced() { return nRequestedMasternodeAssets > MASTERNODE_SYNC_LIST; }
bool IsWinnersListSynced() { return nRequestedMasternodeAssets > MASTERNODE_SYNC_MNW; } bool IsWinnersListSynced() { return nRequestedMasternodeAssets > MASTERNODE_SYNC_MNW; }
bool IsSynced() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FINISHED; } bool IsSynced() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FINISHED; }
int GetAssetID() { return nRequestedMasternodeAssets; } int GetAssetID() { return nRequestedMasternodeAssets; }
int GetAttempt() { return nRequestedMasternodeAttempt; } int GetAttempt() { return nRequestedMasternodeAttempt; }
void BumpAssetLastTime(std::string strFuncName);
int64_t GetAssetStartTime() { return nTimeAssetSyncStarted; } int64_t GetAssetStartTime() { return nTimeAssetSyncStarted; }
std::string GetAssetName(); std::string GetAssetName();
std::string GetSyncStatus(); std::string GetSyncStatus();
@ -84,7 +77,7 @@ public:
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
void ProcessTick(); void ProcessTick();
void UpdatedBlockTip(const CBlockIndex *pindex); void UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload);
}; };
#endif #endif

View File

@ -627,7 +627,7 @@ bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos)
pmn->Check(); pmn->Check();
Relay(); Relay();
} }
masternodeSync.AddedMasternodeList(); masternodeSync.BumpAssetLastTime("CMasternodeBroadcast::Update");
} }
return true; return true;
@ -890,7 +890,7 @@ bool CMasternodePing::CheckAndUpdate(CMasternode* pmn, bool fFromNewBroadcast, i
if(!masternodeSync.IsMasternodeListSynced() && !pmn->IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS/2)) { if(!masternodeSync.IsMasternodeListSynced() && !pmn->IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS/2)) {
// let's bump sync timeout // let's bump sync timeout
LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- bumping sync timeout, masternode=%s\n", vin.prevout.ToStringShort()); 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 // let's store this ping as the last one

View File

@ -1390,14 +1390,13 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb)
CMasternode* pmn = Find(mnb.vin); CMasternode* pmn = Find(mnb.vin);
if(pmn == NULL) { if(pmn == NULL) {
CMasternode mn(mnb); if(Add(mnb)) {
if(Add(mn)) { masternodeSync.BumpAssetLastTime("CMasternodeMan::UpdateMasternodeList - new");
masternodeSync.AddedMasternodeList();
} }
} else { } else {
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second; CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
if(pmn->UpdateFromNewBroadcast(mnb)) { if(pmn->UpdateFromNewBroadcast(mnb)) {
masternodeSync.AddedMasternodeList(); masternodeSync.BumpAssetLastTime("CMasternodeMan::UpdateMasternodeList - seen");
mapSeenMasternodeBroadcast.erase(mnbOld.GetHash()); 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) { 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()); LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen update\n", mnb.vin.prevout.ToStringShort());
mapSeenMasternodeBroadcast[hash].first = GetTime(); mapSeenMasternodeBroadcast[hash].first = GetTime();
masternodeSync.AddedMasternodeList(); masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - seen");
} }
// did we ask this node for it? // did we ask this node for it?
if(pfrom && IsMnbRecoveryRequested(hash) && GetTime() < mMnbRecoveryRequests[hash].first) { if(pfrom && IsMnbRecoveryRequested(hash) && GetTime() < mMnbRecoveryRequests[hash].first) {
@ -1471,7 +1470,7 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBr
if(mnb.CheckOutpoint(nDos)) { if(mnb.CheckOutpoint(nDos)) {
Add(mnb); Add(mnb);
masternodeSync.AddedMasternodeList(); masternodeSync.BumpAssetLastTime("CMasternodeMan::CheckMnbAndUpdateMasternodeList - new");
// if it matches our Masternode privkey... // if it matches our Masternode privkey...
if(fMasterNode && mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode) { if(fMasterNode && mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode) {
mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE; mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
@ -1500,8 +1499,8 @@ void CMasternodeMan::UpdateLastPaid()
{ {
LOCK(cs); LOCK(cs);
if(fLiteMode) return; if(fLiteMode || !pCurrentBlockIndex) return;
if(!pCurrentBlockIndex) return; if(!masternodeSync.IsWinnersListSynced() || vMasternodes.empty()) return;
static bool IsFirstRun = true; static bool IsFirstRun = true;
// Do full scan on first run or if we are not a masternode // Do full scan on first run or if we are not a masternode
@ -1515,8 +1514,7 @@ void CMasternodeMan::UpdateLastPaid()
mn.UpdateLastPaid(pCurrentBlockIndex, nMaxBlocksToScanBack); mn.UpdateLastPaid(pCurrentBlockIndex, nMaxBlocksToScanBack);
} }
// every time is like the first time if winners list is not synced IsFirstRun = false;
IsFirstRun = !masternodeSync.IsWinnersListSynced();
} }
bool CMasternodeMan::UpdateLastDsq(const CTxIn& vin) bool CMasternodeMan::UpdateLastDsq(const CTxIn& vin)

View File

@ -173,6 +173,7 @@ UniValue mnsync(const UniValue& params, bool fHelp)
if(strMode == "reset") if(strMode == "reset")
{ {
masternodeSync.Reset(); masternodeSync.Reset();
masternodeSync.SwitchToNextAsset();
return "success"; return "success";
} }
return "failure"; return "failure";

View File

@ -38,7 +38,6 @@
#include "instantx.h" #include "instantx.h"
#include "masternode-payments.h" #include "masternode-payments.h"
#include "masternode-sync.h"
#include <sstream> #include <sstream>
@ -3456,8 +3455,6 @@ bool ProcessNewBlock(const CChainParams& chainparams, const CBlock* pblock, bool
if (!ActivateBestChain(state, chainparams, pblock)) if (!ActivateBestChain(state, chainparams, pblock))
return error("%s: ActivateBestChain failed", __func__); return error("%s: ActivateBestChain failed", __func__);
masternodeSync.IsBlockchainSynced(true);
LogPrintf("%s : ACCEPTED\n", __func__); LogPrintf("%s : ACCEPTED\n", __func__);
return true; return true;
} }