Fix sync issues (#1225)

* Store time we saw mnb last time, bump sync timeout
if we received seen mnb but we are too close to MASTERNODE_NEW_START_REQUIRED_SECONDS

* Reset blockchain sync status if new blocks were accepted during sync

* Add some debug log output

* wait for at least one new block to be accepted

* bump CGovernanceManager-Version
This commit is contained in:
UdjinM6 2016-12-26 10:44:36 +04:00 committed by GitHub
parent 70b374062b
commit 34fd8daf5a
7 changed files with 59 additions and 17 deletions

View File

@ -20,7 +20,7 @@ std::map<uint256, int64_t> mapAskedForGovernanceObject;
int nSubmittedFinalBudget; int nSubmittedFinalBudget;
const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-6"; const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-7";
CGovernanceManager::CGovernanceManager() CGovernanceManager::CGovernanceManager()
: pCurrentBlockIndex(NULL), : pCurrentBlockIndex(NULL),

View File

@ -4013,6 +4013,8 @@ bool ProcessNewBlock(CValidationState& state, const CChainParams& chainparams, c
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;
} }
@ -5145,7 +5147,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
if(mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)){ if(mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)){
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000); ss.reserve(1000);
ss << mnodeman.mapSeenMasternodeBroadcast[inv.hash]; ss << mnodeman.mapSeenMasternodeBroadcast[inv.hash].second;
// backward compatibility patch // backward compatibility patch
if(pfrom->nVersion < 70204) { if(pfrom->nVersion < 70204) {
ss << (int64_t)0; ss << (int64_t)0;

View File

@ -17,23 +17,52 @@
class CMasternodeSync; class CMasternodeSync;
CMasternodeSync masternodeSync; CMasternodeSync masternodeSync;
bool CMasternodeSync::IsBlockchainSynced() bool CMasternodeSync::IsBlockchainSynced(bool fBlockAccepted)
{ {
static bool fBlockchainSynced = false; static bool fBlockchainSynced = false;
static int64_t nTimeLastProcess = GetTime(); static int64_t nTimeLastProcess = GetTime();
static int nSkipped = 0;
static bool fFirstBlockAccepted = false;
// if the last call to this function was more than 60 minutes ago (client was in sleep mode) reset the sync process // 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) { if(GetTime() - nTimeLastProcess > 60*60) {
Reset(); Reset();
fBlockchainSynced = false; fBlockchainSynced = false;
} }
if(!pCurrentBlockIndex || !pindexBestHeader || fImporting || fReindex) return 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(); 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(fBlockchainSynced) return true;
if(!pCurrentBlockIndex || !pindexBestHeader || fImporting || fReindex) return false;
if(fCheckpointsEnabled && pCurrentBlockIndex->nHeight < Checkpoints::GetTotalBlocksEstimate(Params().Checkpoints())) if(fCheckpointsEnabled && pCurrentBlockIndex->nHeight < Checkpoints::GetTotalBlocksEstimate(Params().Checkpoints()))
return false; return false;
// wait for at least one new block to be accepted
if(!fFirstBlockAccepted) return false;
// same as !IsInitialBlockDownload() but no cs_main needed here // same as !IsInitialBlockDownload() but no cs_main needed here
int64_t nMaxBlockTime = std::max(pCurrentBlockIndex->GetBlockTime(), pindexBestHeader->GetBlockTime()); int64_t nMaxBlockTime = std::max(pCurrentBlockIndex->GetBlockTime(), pindexBestHeader->GetBlockTime());
fBlockchainSynced = pindexBestHeader->nHeight - pCurrentBlockIndex->nHeight < 24 * 6 && fBlockchainSynced = pindexBestHeader->nHeight - pCurrentBlockIndex->nHeight < 24 * 6 &&
@ -172,7 +201,7 @@ void ReleaseNodes(const std::vector<CNode*> &vNodesCopy)
void CMasternodeSync::ProcessTick() void CMasternodeSync::ProcessTick()
{ {
static int nTick = 0; static int nTick = 0;
if(nTick++ % 6 != 0) return; if(nTick++ % MASTERNODE_SYNC_TICK_SECONDS != 0) return;
if(!pCurrentBlockIndex) return; if(!pCurrentBlockIndex) return;
//the actual count of masternodes we have currently //the actual count of masternodes we have currently
@ -214,6 +243,9 @@ void CMasternodeSync::ProcessTick()
!IsBlockchainSynced() && nRequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS) !IsBlockchainSynced() && nRequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS)
{ {
LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nRequestedMasternodeAttempt %d -- blockchain is not synced yet\n", nTick, nRequestedMasternodeAssets, nRequestedMasternodeAttempt); 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;
} }

View File

@ -21,6 +21,7 @@ static const int MASTERNODE_SYNC_GOVOBJ = 10;
static const int MASTERNODE_SYNC_GOVOBJ_VOTE = 11; static const int MASTERNODE_SYNC_GOVOBJ_VOTE = 11;
static const int MASTERNODE_SYNC_FINISHED = 999; static const int MASTERNODE_SYNC_FINISHED = 999;
static const int MASTERNODE_SYNC_TICK_SECONDS = 6;
static const int MASTERNODE_SYNC_TIMEOUT_SECONDS = 30; // our blocks are 2.5 minutes so 30 seconds should be fine static const int MASTERNODE_SYNC_TIMEOUT_SECONDS = 30; // our blocks are 2.5 minutes so 30 seconds should be fine
extern CMasternodeSync masternodeSync; extern CMasternodeSync masternodeSync;
@ -64,7 +65,7 @@ public:
void AddedGovernanceItem() { nTimeLastGovernanceItem = GetTime(); }; void AddedGovernanceItem() { nTimeLastGovernanceItem = GetTime(); };
bool IsFailed() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FAILED; } bool IsFailed() { return nRequestedMasternodeAssets == MASTERNODE_SYNC_FAILED; }
bool IsBlockchainSynced(); bool IsBlockchainSynced(bool fBlockAccepted = false);
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; }

View File

@ -911,7 +911,7 @@ bool CMasternodePing::CheckAndUpdate(CMasternode* pmn, int& nDos)
CMasternodeBroadcast mnb(*pmn); CMasternodeBroadcast mnb(*pmn);
uint256 hash = mnb.GetHash(); uint256 hash = mnb.GetHash();
if (mnodeman.mapSeenMasternodeBroadcast.count(hash)) { if (mnodeman.mapSeenMasternodeBroadcast.count(hash)) {
mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = *this; mnodeman.mapSeenMasternodeBroadcast[hash].second.lastPing = *this;
} }
pmn->Check(true); // force update, ignoring cache pmn->Check(true); // force update, ignoring cache

View File

@ -15,7 +15,7 @@
/** Masternode manager */ /** Masternode manager */
CMasternodeMan mnodeman; CMasternodeMan mnodeman;
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-2"; const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-3";
struct CompareLastPaidBlock struct CompareLastPaidBlock
{ {
@ -804,7 +804,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
nInvCount++; nInvCount++;
if (!mapSeenMasternodeBroadcast.count(hash)) { if (!mapSeenMasternodeBroadcast.count(hash)) {
mapSeenMasternodeBroadcast.insert(std::make_pair(hash, mnb)); mapSeenMasternodeBroadcast.insert(std::make_pair(hash, std::make_pair(GetTime(), mnb)));
} }
if (vin == mn.vin) { if (vin == mn.vin) {
@ -1281,7 +1281,7 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb)
{ {
LOCK(cs); LOCK(cs);
mapSeenMasternodePing.insert(std::make_pair(mnb.lastPing.GetHash(), mnb.lastPing)); mapSeenMasternodePing.insert(std::make_pair(mnb.lastPing.GetHash(), mnb.lastPing));
mapSeenMasternodeBroadcast.insert(std::make_pair(mnb.GetHash(), mnb)); mapSeenMasternodeBroadcast.insert(std::make_pair(mnb.GetHash(), std::make_pair(GetTime(), mnb)));
LogPrintf("CMasternodeMan::UpdateMasternodeList -- masternode=%s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString()); LogPrintf("CMasternodeMan::UpdateMasternodeList -- masternode=%s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
@ -1292,7 +1292,7 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb)
masternodeSync.AddedMasternodeList(); masternodeSync.AddedMasternodeList();
} }
} else { } else {
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()]; CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
if(pmn->UpdateFromNewBroadcast(mnb)) { if(pmn->UpdateFromNewBroadcast(mnb)) {
masternodeSync.AddedMasternodeList(); masternodeSync.AddedMasternodeList();
mapSeenMasternodeBroadcast.erase(mnbOld.GetHash()); mapSeenMasternodeBroadcast.erase(mnbOld.GetHash());
@ -1308,11 +1308,18 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, i
nDos = 0; nDos = 0;
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.vin.prevout.ToStringShort()); LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.vin.prevout.ToStringShort());
if(mapSeenMasternodeBroadcast.count(mnb.GetHash())) { //seen uint256 hash = mnb.GetHash();
if(mapSeenMasternodeBroadcast.count(hash)) { //seen
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen\n", mnb.vin.prevout.ToStringShort()); LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen\n", mnb.vin.prevout.ToStringShort());
// less then 2 pings left before this MN goes into non-recoverable state, bump sync timeout
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();
}
return true; return true;
} }
mapSeenMasternodeBroadcast.insert(std::make_pair(mnb.GetHash(), mnb)); mapSeenMasternodeBroadcast.insert(std::make_pair(hash, std::make_pair(GetTime(), mnb)));
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.vin.prevout.ToStringShort()); LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.vin.prevout.ToStringShort());
@ -1324,12 +1331,12 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, i
// search Masternode list // search Masternode list
CMasternode* pmn = Find(mnb.vin); CMasternode* pmn = Find(mnb.vin);
if(pmn) { if(pmn) {
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()]; CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
if(!mnb.Update(pmn, nDos)) { if(!mnb.Update(pmn, nDos)) {
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort()); LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
return false; return false;
} }
if(mnb.GetHash() != mnbOld.GetHash()) { if(hash != mnbOld.GetHash()) {
mapSeenMasternodeBroadcast.erase(mnbOld.GetHash()); mapSeenMasternodeBroadcast.erase(mnbOld.GetHash());
} }
} else { } else {
@ -1509,7 +1516,7 @@ void CMasternodeMan::SetMasternodeLastPing(const CTxIn& vin, const CMasternodePi
CMasternodeBroadcast mnb(*pMN); CMasternodeBroadcast mnb(*pMN);
uint256 hash = mnb.GetHash(); uint256 hash = mnb.GetHash();
if(mapSeenMasternodeBroadcast.count(hash)) { if(mapSeenMasternodeBroadcast.count(hash)) {
mapSeenMasternodeBroadcast[hash].lastPing = mnp; mapSeenMasternodeBroadcast[hash].second.lastPing = mnp;
} }
} }

View File

@ -144,7 +144,7 @@ private:
public: public:
// Keep track of all broadcasts I've seen // Keep track of all broadcasts I've seen
std::map<uint256, CMasternodeBroadcast> mapSeenMasternodeBroadcast; std::map<uint256, std::pair<int64_t, CMasternodeBroadcast> > mapSeenMasternodeBroadcast;
// Keep track of all pings I've seen // Keep track of all pings I've seen
std::map<uint256, CMasternodePing> mapSeenMasternodePing; std::map<uint256, CMasternodePing> mapSeenMasternodePing;
// Keep track of all verifications I've seen // Keep track of all verifications I've seen