Line data Source code
1 : // Copyright (c) 2014-2025 The Dash Core developers 2 : // Distributed under the MIT/X11 software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #include <masternode/sync.h> 6 : 7 : #include <chain.h> 8 : #include <logging.h> 9 : #include <util/time.h> 10 : #include <util/translation.h> 11 : 12 : #include <cassert> 13 : 14 0 : void NullNodeSyncNotifier::SyncReset() { assert(false); } 15 0 : void NullNodeSyncNotifier::SyncFinished() { assert(false); } 16 : 17 6138 : CMasternodeSync::CMasternodeSync(std::unique_ptr<NodeSyncNotifier>&& sync_notifier) : 18 : nTimeAssetSyncStarted{GetTime()}, 19 : nTimeLastBumped{GetTime()}, 20 : m_sync_notifier{std::move(sync_notifier)} 21 3069 : { 22 : assert(m_sync_notifier != nullptr); 23 3069 : } 24 : 25 6138 : CMasternodeSync::~CMasternodeSync() = default; 26 : 27 10345 : void CMasternodeSync::Reset(bool fForce, bool fNotifyReset) 28 : { 29 : // Avoid resetting the sync process if we just "recently" received a new block 30 10345 : if (!fForce) { 31 4013 : if (GetTime() - nTimeLastUpdateBlockTip < MASTERNODE_SYNC_RESET_SECONDS) { 32 3879 : return; 33 : } 34 134 : } 35 6466 : nCurrentAsset = MASTERNODE_SYNC_BLOCKCHAIN; 36 6466 : nTriedPeerCount = 0; 37 6466 : nTimeAssetSyncStarted = GetTime(); 38 6466 : nTimeLastBumped = GetTime(); 39 6466 : nTimeLastUpdateBlockTip = 0; 40 6466 : fReachedBestHeader = false; 41 6466 : if (fNotifyReset) { 42 6466 : m_sync_notifier->SyncReset(); 43 6466 : } 44 10345 : } 45 : 46 374228 : void CMasternodeSync::BumpAssetLastTime(const std::string& strFuncName) 47 : { 48 374228 : if (IsSynced()) return; 49 371866 : nTimeLastBumped = GetTime(); 50 371866 : LogPrint(BCLog::MNSYNC, "CMasternodeSync::BumpAssetLastTime -- %s\n", strFuncName); 51 374228 : } 52 : 53 8578 : std::string CMasternodeSync::GetAssetName() const 54 : { 55 8578 : switch(nCurrentAsset) 56 : { 57 1863 : case(MASTERNODE_SYNC_BLOCKCHAIN): return "MASTERNODE_SYNC_BLOCKCHAIN"; 58 5121 : case(MASTERNODE_SYNC_GOVERNANCE): return "MASTERNODE_SYNC_GOVERNANCE"; 59 1594 : case MASTERNODE_SYNC_FINISHED: return "MASTERNODE_SYNC_FINISHED"; 60 0 : default: return "UNKNOWN"; 61 : } 62 8578 : } 63 : 64 1758 : void CMasternodeSync::SwitchToNextAsset() 65 : { 66 1758 : switch(nCurrentAsset) 67 : { 68 : case(MASTERNODE_SYNC_BLOCKCHAIN): 69 901 : LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); 70 901 : nCurrentAsset = MASTERNODE_SYNC_GOVERNANCE; 71 901 : LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName()); 72 901 : break; 73 : case(MASTERNODE_SYNC_GOVERNANCE): 74 857 : LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted); 75 857 : nCurrentAsset = MASTERNODE_SYNC_FINISHED; 76 857 : m_sync_notifier->SyncFinished(); 77 857 : LogPrintf("CMasternodeSync::SwitchToNextAsset -- Sync has finished\n"); 78 : 79 857 : break; 80 : } 81 1758 : nTriedPeerCount = 0; 82 1758 : nTimeAssetSyncStarted = GetTime(); 83 1758 : BumpAssetLastTime("CMasternodeSync::SwitchToNextAsset"); 84 1758 : } 85 : 86 0 : std::string CMasternodeSync::GetSyncStatus() const 87 : { 88 0 : switch (nCurrentAsset) { 89 0 : case MASTERNODE_SYNC_BLOCKCHAIN: return _("Synchronizing blockchain…").translated; 90 0 : case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects…").translated; 91 0 : case MASTERNODE_SYNC_FINISHED: return _("Synchronization finished").translated; 92 0 : default: return ""; 93 : } 94 0 : } 95 : 96 244470 : void CMasternodeSync::AcceptedBlockHeader(const CBlockIndex *pindexNew) 97 : { 98 244470 : LogPrint(BCLog::MNSYNC, "CMasternodeSync::AcceptedBlockHeader -- pindexNew->nHeight: %d\n", pindexNew->nHeight); 99 : 100 244470 : if (!IsBlockchainSynced()) { 101 : // Postpone timeout each time new block header arrives while we are still syncing blockchain 102 145204 : BumpAssetLastTime("CMasternodeSync::AcceptedBlockHeader"); 103 145204 : } 104 244470 : } 105 : 106 192109 : void CMasternodeSync::NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) 107 : { 108 192109 : if (pindexNew == nullptr) { 109 0 : return; 110 : } 111 192109 : LogPrint(BCLog::MNSYNC, "CMasternodeSync::NotifyHeaderTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); 112 192109 : if (IsSynced()) 113 91137 : return; 114 : 115 100972 : if (!IsBlockchainSynced()) { 116 : // Postpone timeout each time new block arrives while we are still syncing blockchain 117 100860 : BumpAssetLastTime("CMasternodeSync::NotifyHeaderTip"); 118 100860 : } 119 192109 : } 120 : 121 224210 : void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexTip, const CBlockIndex *pindexNew, bool fInitialDownload) 122 : { 123 224210 : LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); 124 224210 : nTimeLastUpdateBlockTip = GetTime<std::chrono::seconds>().count(); 125 : 126 224210 : if (IsSynced()) 127 99243 : return; 128 : 129 124967 : if (!IsBlockchainSynced()) { 130 : // Postpone timeout each time new block arrives while we are still syncing blockchain 131 124882 : BumpAssetLastTime("CMasternodeSync::UpdatedBlockTip"); 132 124882 : } 133 : 134 124967 : if (fInitialDownload) { 135 : // switched too early 136 16652 : if (IsBlockchainSynced()) { 137 0 : Reset(true); 138 0 : } 139 : 140 : // no need to check any further while still in IBD mode 141 16652 : return; 142 : } 143 : 144 : // Note: since we sync headers first, it should be ok to use this 145 108315 : if (pindexTip == nullptr) return; 146 108315 : bool fReachedBestHeaderNew = pindexNew->GetBlockHash() == pindexTip->GetBlockHash(); 147 : 148 108315 : if (fReachedBestHeader && !fReachedBestHeaderNew) { 149 : // Switching from true to false means that we previously stuck syncing headers for some reason, 150 : // probably initial timeout was not enough, 151 : // because there is no way we can update tip not having best header 152 6308 : Reset(true); 153 6308 : } 154 : 155 108315 : fReachedBestHeader = fReachedBestHeaderNew; 156 108315 : LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d pindexTip->nHeight: %d fInitialDownload=%d fReachedBestHeader=%d\n", 157 : pindexNew->nHeight, pindexTip->nHeight, fInitialDownload, fReachedBestHeader); 158 224210 : }