2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
2015-07-15 04:44:58 +02:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2015-07-29 05:26:08 +02:00
# include "activemasternode.h"
2016-10-10 23:11:20 +02:00
# include "checkpoints.h"
2016-04-15 04:54:11 +02:00
# include "governance.h"
2016-08-28 12:12:14 +02:00
# include "main.h"
2015-07-15 04:44:58 +02:00
# include "masternode.h"
2016-08-28 12:12:14 +02:00
# include "masternode-payments.h"
# include "masternode-sync.h"
2015-07-17 11:17:15 +02:00
# include "masternodeman.h"
2016-09-27 09:50:04 +02:00
# include "netfulfilledman.h"
2015-08-15 15:27:26 +02:00
# include "spork.h"
2015-07-15 04:44:58 +02:00
# include "util.h"
class CMasternodeSync ;
CMasternodeSync masternodeSync ;
2017-01-11 00:33:14 +01:00
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 ;
}
2016-12-26 07:44:36 +01:00
bool CMasternodeSync : : IsBlockchainSynced ( bool fBlockAccepted )
2015-07-26 21:37:01 +02:00
{
2015-08-04 01:23:36 +02:00
static bool fBlockchainSynced = false ;
2016-12-26 07:44:36 +01:00
static int nSkipped = 0 ;
static bool fFirstBlockAccepted = false ;
2015-08-04 23:15:24 +02:00
2017-05-31 05:48:47 +02:00
if ( ! pCurrentBlockIndex | | ! pindexBestHeader | | fImporting | | fReindex ) return false ;
static int64_t nTimeLastProcess = GetTime ( ) ;
2015-08-11 23:54:42 +02:00
// if the last call to this function was more than 60 minutes ago (client was in sleep mode) reset the sync process
2016-10-22 18:52:14 +02:00
if ( GetTime ( ) - nTimeLastProcess > 60 * 60 ) {
2015-08-04 23:15:24 +02:00
Reset ( ) ;
fBlockchainSynced = false ;
}
2016-12-26 07:44:36 +01:00
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 ) ;
2016-10-22 18:52:14 +02:00
nTimeLastProcess = GetTime ( ) ;
2016-12-26 07:44:36 +01:00
nSkipped = 0 ;
2015-08-04 23:15:24 +02:00
2015-08-04 01:23:36 +02:00
if ( fBlockchainSynced ) return true ;
2016-12-26 07:44:36 +01:00
2016-10-10 23:11:20 +02:00
if ( fCheckpointsEnabled & & pCurrentBlockIndex - > nHeight < Checkpoints : : GetTotalBlocksEstimate ( Params ( ) . Checkpoints ( ) ) )
return false ;
2015-08-04 01:23:36 +02:00
2017-03-05 20:16:12 +01:00
std : : vector < CNode * > vNodesCopy = CopyNodeVector ( ) ;
2017-01-11 00:33:14 +01:00
// We have enough peers and assume most of them are synced
2017-03-20 02:20:52 +01:00
if ( vNodesCopy . size ( ) > = MASTERNODE_SYNC_ENOUGH_PEERS ) {
2017-01-11 00:33:14 +01:00
// 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 ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2017-01-11 00:33:14 +01:00
return true ;
}
}
}
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2017-01-11 00:33:14 +01:00
2016-12-26 07:44:36 +01:00
// wait for at least one new block to be accepted
if ( ! fFirstBlockAccepted ) return false ;
2016-09-27 10:56:10 +02:00
// same as !IsInitialBlockDownload() but no cs_main needed here
2016-12-02 13:53:28 +01:00
int64_t nMaxBlockTime = std : : max ( pCurrentBlockIndex - > GetBlockTime ( ) , pindexBestHeader - > GetBlockTime ( ) ) ;
2016-09-27 10:56:10 +02:00
fBlockchainSynced = pindexBestHeader - > nHeight - pCurrentBlockIndex - > nHeight < 24 * 6 & &
GetTime ( ) - nMaxBlockTime < Params ( ) . MaxTipAge ( ) ;
2015-08-03 22:42:18 +02:00
2016-09-27 10:56:10 +02:00
return fBlockchainSynced ;
2015-07-26 21:37:01 +02:00
}
2016-08-28 12:12:14 +02:00
void CMasternodeSync : : Fail ( )
{
nTimeLastFailure = GetTime ( ) ;
nRequestedMasternodeAssets = MASTERNODE_SYNC_FAILED ;
}
2015-08-04 20:21:27 +02:00
void CMasternodeSync : : Reset ( )
2016-08-17 09:08:25 +02:00
{
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL ;
nRequestedMasternodeAttempt = 0 ;
nTimeAssetSyncStarted = GetTime ( ) ;
nTimeLastMasternodeList = GetTime ( ) ;
2016-09-21 16:45:29 +02:00
nTimeLastPaymentVote = GetTime ( ) ;
2016-12-06 17:40:37 +01:00
nTimeLastGovernanceItem = GetTime ( ) ;
2016-08-28 12:12:14 +02:00
nTimeLastFailure = 0 ;
2015-07-15 04:44:58 +02:00
}
2016-06-08 08:57:16 +02:00
std : : string CMasternodeSync : : GetAssetName ( )
{
2016-08-28 12:12:14 +02:00
switch ( nRequestedMasternodeAssets )
2016-06-08 08:57:16 +02:00
{
2016-08-28 12:12:14 +02:00
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 " ;
case ( MASTERNODE_SYNC_FAILED ) : return " MASTERNODE_SYNC_FAILED " ;
case MASTERNODE_SYNC_FINISHED : return " MASTERNODE_SYNC_FINISHED " ;
default : return " UNKNOWN " ;
2016-06-08 08:57:16 +02:00
}
}
2016-08-28 12:12:14 +02:00
void CMasternodeSync : : SwitchToNextAsset ( )
2015-07-15 04:44:58 +02:00
{
2016-08-28 12:12:14 +02:00
switch ( nRequestedMasternodeAssets )
2015-07-15 04:44:58 +02:00
{
2016-08-29 21:11:34 +02:00
case ( MASTERNODE_SYNC_FAILED ) :
throw std : : runtime_error ( " Can't switch to next asset from failed, should use Reset() first! " ) ;
break ;
2015-07-17 12:26:24 +02:00
case ( MASTERNODE_SYNC_INITIAL ) :
2016-09-27 09:50:04 +02:00
ClearFulfilledRequests ( ) ;
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAssets = MASTERNODE_SYNC_SPORKS ;
2017-01-18 16:23:49 +01:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Starting %s \n " , GetAssetName ( ) ) ;
2015-07-17 05:03:42 +02:00
break ;
2015-07-17 12:26:24 +02:00
case ( MASTERNODE_SYNC_SPORKS ) :
2017-05-31 05:49:09 +02:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss \n " , GetAssetName ( ) , GetTime ( ) - nTimeAssetSyncStarted ) ;
2016-08-28 12:12:14 +02:00
nTimeLastMasternodeList = GetTime ( ) ;
nRequestedMasternodeAssets = MASTERNODE_SYNC_LIST ;
2017-01-18 16:23:49 +01:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Starting %s \n " , GetAssetName ( ) ) ;
2015-07-15 04:44:58 +02:00
break ;
case ( MASTERNODE_SYNC_LIST ) :
2017-05-31 05:49:09 +02:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss \n " , GetAssetName ( ) , GetTime ( ) - nTimeAssetSyncStarted ) ;
2016-09-21 16:45:29 +02:00
nTimeLastPaymentVote = GetTime ( ) ;
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAssets = MASTERNODE_SYNC_MNW ;
2017-01-18 16:23:49 +01:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Starting %s \n " , GetAssetName ( ) ) ;
2015-07-15 04:44:58 +02:00
break ;
case ( MASTERNODE_SYNC_MNW ) :
2017-05-31 05:49:09 +02:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss \n " , GetAssetName ( ) , GetTime ( ) - nTimeAssetSyncStarted ) ;
2016-12-06 17:40:37 +01:00
nTimeLastGovernanceItem = GetTime ( ) ;
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAssets = MASTERNODE_SYNC_GOVERNANCE ;
2017-01-18 16:23:49 +01:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Starting %s \n " , GetAssetName ( ) ) ;
2015-07-15 04:44:58 +02:00
break ;
2016-06-08 08:57:16 +02:00
case ( MASTERNODE_SYNC_GOVERNANCE ) :
2017-05-31 05:49:09 +02:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Completed %s in %ss \n " , GetAssetName ( ) , GetTime ( ) - nTimeAssetSyncStarted ) ;
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED ;
2016-02-19 19:09:54 +01:00
uiInterface . NotifyAdditionalDataSyncProgressChanged ( 1 ) ;
2016-08-05 18:25:03 +02:00
//try to activate our masternode if possible
2016-08-05 21:49:45 +02:00
activeMasternode . ManageState ( ) ;
2016-09-27 09:50:04 +02:00
TRY_LOCK ( cs_vNodes , lockRecv ) ;
2017-05-31 05:49:09 +02:00
if ( lockRecv ) {
BOOST_FOREACH ( CNode * pnode , vNodes ) {
netfulfilledman . AddFulfilledRequest ( pnode - > addr , " full-sync " ) ;
}
2016-09-27 09:50:04 +02:00
}
2017-05-31 05:49:09 +02:00
LogPrintf ( " CMasternodeSync::SwitchToNextAsset -- Sync has finished \n " ) ;
2016-09-27 09:50:04 +02:00
2015-07-15 04:44:58 +02:00
break ;
}
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAttempt = 0 ;
nTimeAssetSyncStarted = GetTime ( ) ;
2015-07-15 04:44:58 +02:00
}
2015-08-15 17:53:55 +02:00
std : : string CMasternodeSync : : GetSyncStatus ( )
{
2016-08-28 12:12:14 +02:00
switch ( masternodeSync . nRequestedMasternodeAssets ) {
case MASTERNODE_SYNC_INITIAL : return _ ( " Synchronization pending... " ) ;
case MASTERNODE_SYNC_SPORKS : return _ ( " Synchronizing sporks... " ) ;
case MASTERNODE_SYNC_LIST : return _ ( " Synchronizing masternodes... " ) ;
2016-09-21 16:45:29 +02:00
case MASTERNODE_SYNC_MNW : return _ ( " Synchronizing masternode payments... " ) ;
2016-08-28 12:12:14 +02:00
case MASTERNODE_SYNC_GOVERNANCE : return _ ( " Synchronizing governance objects... " ) ;
case MASTERNODE_SYNC_FAILED : return _ ( " Synchronization failed " ) ;
case MASTERNODE_SYNC_FINISHED : return _ ( " Synchronization finished " ) ;
default : return " " ;
2015-08-15 17:53:55 +02:00
}
}
2015-07-29 06:16:11 +02:00
void CMasternodeSync : : ProcessMessage ( CNode * pfrom , std : : string & strCommand , CDataStream & vRecv )
{
2016-02-17 23:18:57 +01:00
if ( strCommand = = NetMsgType : : SYNCSTATUSCOUNT ) { //Sync status count
2015-07-29 06:16:11 +02:00
2016-08-29 21:11:34 +02:00
//do not care about stats if sync process finished or failed
if ( IsSynced ( ) | | IsFailed ( ) ) return ;
2015-07-29 06:16:11 +02:00
2016-09-11 19:49:40 +02:00
int nItemID ;
int nCount ;
vRecv > > nItemID > > nCount ;
2016-10-22 18:52:14 +02:00
LogPrintf ( " SYNCSTATUSCOUNT -- got inventory count: nItemID=%d nCount=%d peer=%d \n " , nItemID , nCount , pfrom - > id ) ;
2015-07-30 10:51:48 +02:00
}
}
2016-09-27 09:50:04 +02:00
void CMasternodeSync : : ClearFulfilledRequests ( )
2015-07-30 10:51:48 +02:00
{
2015-07-30 15:44:18 +02:00
TRY_LOCK ( cs_vNodes , lockRecv ) ;
if ( ! lockRecv ) return ;
2015-07-30 10:51:48 +02:00
BOOST_FOREACH ( CNode * pnode , vNodes )
{
2016-09-27 09:50:04 +02:00
netfulfilledman . RemoveFulfilledRequest ( pnode - > addr , " spork-sync " ) ;
netfulfilledman . RemoveFulfilledRequest ( pnode - > addr , " masternode-list-sync " ) ;
netfulfilledman . RemoveFulfilledRequest ( pnode - > addr , " masternode-payment-sync " ) ;
netfulfilledman . RemoveFulfilledRequest ( pnode - > addr , " governance-sync " ) ;
netfulfilledman . RemoveFulfilledRequest ( pnode - > addr , " full-sync " ) ;
2015-07-29 06:16:11 +02:00
}
}
2016-08-28 12:12:14 +02:00
void CMasternodeSync : : ProcessTick ( )
2015-07-15 04:44:58 +02:00
{
2016-08-28 12:12:14 +02:00
static int nTick = 0 ;
2016-12-26 07:44:36 +01:00
if ( nTick + + % MASTERNODE_SYNC_TICK_SECONDS ! = 0 ) return ;
2016-03-02 22:20:04 +01:00
if ( ! pCurrentBlockIndex ) return ;
2016-02-04 20:29:09 +01:00
//the actual count of masternodes we have currently
2016-10-17 20:54:28 +02:00
int nMnCount = mnodeman . CountMasternodes ( ) ;
2016-10-22 18:52:14 +02:00
if ( fDebug ) LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nMnCount %d \n " , nTick , nMnCount ) ;
2015-07-19 10:19:54 +02:00
2016-02-04 20:29:09 +01:00
// RESET SYNCING INCASE OF FAILURE
{
if ( IsSynced ( ) ) {
2016-08-17 09:08:25 +02:00
/*
2017-02-19 22:02:33 +01:00
Resync if we lost all masternodes from sleep / wake or failed to sync originally
2016-02-04 20:29:09 +01:00
*/
2016-03-08 12:15:22 +01:00
if ( nMnCount = = 0 ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- WARNING: not enough data, restarting sync \n " ) ;
2016-02-04 20:29:09 +01:00
Reset ( ) ;
2016-06-08 08:57:16 +02:00
} else {
2017-03-05 20:16:12 +01:00
std : : vector < CNode * > vNodesCopy = CopyNodeVector ( ) ;
2017-01-17 21:02:38 +01:00
governance . RequestGovernanceObjectVotes ( vNodesCopy ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-08-17 09:08:25 +02:00
return ;
2016-06-08 08:57:16 +02:00
}
2016-02-04 20:29:09 +01:00
}
//try syncing again
2016-08-28 12:12:14 +02:00
if ( IsFailed ( ) ) {
2016-08-29 21:11:34 +02:00
if ( nTimeLastFailure + ( 1 * 60 ) < GetTime ( ) ) { // 1 minute cooldown after failed sync
2016-08-28 12:12:14 +02:00
Reset ( ) ;
2016-08-29 21:11:34 +02:00
}
2015-07-19 10:19:54 +02:00
return ;
2016-02-04 20:29:09 +01:00
}
2015-07-18 01:49:41 +02:00
}
2015-07-15 04:44:58 +02:00
2016-06-08 08:57:16 +02:00
// INITIAL SYNC SETUP / LOG REPORTING
2016-08-28 12:12:14 +02:00
double nSyncProgress = double ( nRequestedMasternodeAttempt + ( nRequestedMasternodeAssets - 1 ) * 8 ) / ( 8 * 4 ) ;
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nRequestedMasternodeAttempt %d nSyncProgress %f \n " , nTick , nRequestedMasternodeAssets , nRequestedMasternodeAttempt , nSyncProgress ) ;
2016-08-05 18:25:03 +02:00
uiInterface . NotifyAdditionalDataSyncProgressChanged ( nSyncProgress ) ;
2015-07-17 11:17:15 +02:00
2016-08-05 18:25:03 +02:00
// sporks synced but blockchain is not, wait until we're almost at a recent block to continue
if ( Params ( ) . NetworkIDString ( ) ! = CBaseChainParams : : REGTEST & &
2016-10-22 18:52:14 +02:00
! IsBlockchainSynced ( ) & & nRequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS )
{
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nRequestedMasternodeAttempt %d -- blockchain is not synced yet \n " , nTick , nRequestedMasternodeAssets , nRequestedMasternodeAttempt ) ;
2016-12-26 07:44:36 +01:00
nTimeLastMasternodeList = GetTime ( ) ;
nTimeLastPaymentVote = GetTime ( ) ;
nTimeLastGovernanceItem = GetTime ( ) ;
2016-10-22 18:52:14 +02:00
return ;
}
2015-07-15 04:44:58 +02:00
2016-09-27 11:02:57 +02:00
if ( nRequestedMasternodeAssets = = MASTERNODE_SYNC_INITIAL | |
( nRequestedMasternodeAssets = = MASTERNODE_SYNC_SPORKS & & IsBlockchainSynced ( ) ) )
{
2016-08-29 21:11:34 +02:00
SwitchToNextAsset ( ) ;
}
2015-07-30 15:44:18 +02:00
2017-03-05 20:16:12 +01:00
std : : vector < CNode * > vNodesCopy = CopyNodeVector ( ) ;
2016-11-28 15:21:50 +01:00
BOOST_FOREACH ( CNode * pnode , vNodesCopy )
2015-07-17 11:17:15 +02:00
{
2017-02-16 16:14:42 +01:00
// Don't try to sync any data from outbound "masternode" connections -
// they are temporary and should be considered unreliable for a sync process.
// Inbound connection this early is most likely a "masternode" connection
2017-07-03 15:14:07 +02:00
// initiated from another node, so skip it too.
2017-02-16 16:14:42 +01:00
if ( pnode - > fMasternode | | ( fMasterNode & & pnode - > fInbound ) ) continue ;
2016-06-08 08:57:16 +02:00
// QUICK MODE (REGTEST ONLY!)
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : REGTEST )
{
2016-08-28 12:12:14 +02:00
if ( nRequestedMasternodeAttempt < = 2 ) {
2016-02-17 23:18:57 +01:00
pnode - > PushMessage ( NetMsgType : : GETSPORKS ) ; //get current network sporks
2016-08-28 12:12:14 +02:00
} else if ( nRequestedMasternodeAttempt < 4 ) {
2016-08-17 09:08:25 +02:00
mnodeman . DsegUpdate ( pnode ) ;
2016-08-28 12:12:14 +02:00
} else if ( nRequestedMasternodeAttempt < 6 ) {
2016-10-17 20:54:28 +02:00
int nMnCount = mnodeman . CountMasternodes ( ) ;
2016-09-21 16:45:29 +02:00
pnode - > PushMessage ( NetMsgType : : MASTERNODEPAYMENTSYNC , nMnCount ) ; //sync payment votes
2017-02-02 09:50:44 +01:00
SendGovernanceSyncRequest ( pnode ) ;
2015-07-23 23:35:14 +02:00
} else {
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED ;
2015-07-17 11:17:15 +02:00
}
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAttempt + + ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2015-07-19 01:25:52 +02:00
return ;
}
2016-06-08 08:57:16 +02:00
// NORMAL NETWORK MODE - TESTNET/MAINNET
2016-08-17 09:08:25 +02:00
{
2016-09-27 09:50:04 +02:00
if ( netfulfilledman . HasFulfilledRequest ( pnode - > addr , " full-sync " ) ) {
2017-02-19 22:02:33 +01:00
// We already fully synced from this node recently,
// disconnect to free this connection slot for another peer.
2016-09-27 09:50:04 +02:00
pnode - > fDisconnect = true ;
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- disconnecting from recently synced peer %d \n " , pnode - > id ) ;
2016-09-27 09:50:04 +02:00
continue ;
}
2016-06-08 08:57:16 +02:00
// SPORK : ALWAYS ASK FOR SPORKS AS WE SYNC (we skip this mode now)
2015-07-20 20:56:02 +02:00
2016-09-27 09:50:04 +02:00
if ( ! netfulfilledman . HasFulfilledRequest ( pnode - > addr , " spork-sync " ) ) {
2016-08-05 18:25:03 +02:00
// only request once from each peer
2016-09-27 09:50:04 +02:00
netfulfilledman . AddFulfilledRequest ( pnode - > addr , " spork-sync " ) ;
2016-06-08 08:57:16 +02:00
// get current network sporks
2016-08-17 09:08:25 +02:00
pnode - > PushMessage ( NetMsgType : : GETSPORKS ) ;
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- requesting sporks from peer %d \n " , nTick , nRequestedMasternodeAssets , pnode - > id ) ;
2016-08-05 18:25:03 +02:00
continue ; // always get sporks first, switch to the next node without waiting for the next tick
2016-06-08 08:57:16 +02:00
}
2016-05-24 21:20:10 +02:00
2016-08-05 18:25:03 +02:00
// MNLIST : SYNC MASTERNODE LIST FROM OTHER CONNECTED CLIENTS
2015-07-15 04:44:58 +02:00
2016-08-28 12:12:14 +02:00
if ( nRequestedMasternodeAssets = = MASTERNODE_SYNC_LIST ) {
2016-10-22 18:52:14 +02:00
LogPrint ( " masternode " , " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastMasternodeList %lld GetTime() %lld diff %lld \n " , nTick , nRequestedMasternodeAssets , nTimeLastMasternodeList , GetTime ( ) , GetTime ( ) - nTimeLastMasternodeList ) ;
2016-08-05 18:25:03 +02:00
// check for timeout first
2017-07-03 15:14:07 +02:00
if ( GetTime ( ) - nTimeLastMasternodeList > MASTERNODE_SYNC_TIMEOUT_SECONDS ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout \n " , nTick , nRequestedMasternodeAssets ) ;
2016-08-28 12:12:14 +02:00
if ( nRequestedMasternodeAttempt = = 0 ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- ERROR: failed to sync %s \n " , GetAssetName ( ) ) ;
2016-08-29 21:11:34 +02:00
// there is no way we can continue without masternode list, fail here and try later
Fail ( ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-08-29 21:11:34 +02:00
return ;
2016-08-28 12:12:14 +02:00
}
SwitchToNextAsset ( ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2015-08-15 15:27:26 +02:00
return ;
}
2016-08-05 18:25:03 +02:00
// only request once from each peer
2016-09-27 09:50:04 +02:00
if ( netfulfilledman . HasFulfilledRequest ( pnode - > addr , " masternode-list-sync " ) ) continue ;
netfulfilledman . AddFulfilledRequest ( pnode - > addr , " masternode-list-sync " ) ;
2015-07-27 05:41:25 +02:00
2016-08-05 18:25:03 +02:00
if ( pnode - > nVersion < mnpayments . GetMinMasternodePaymentsProto ( ) ) continue ;
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAttempt + + ;
2015-07-21 04:24:43 +02:00
2016-08-05 18:25:03 +02:00
mnodeman . DsegUpdate ( pnode ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-02-04 23:48:23 +01:00
return ; //this will cause each peer to get one request each six seconds for the various assets we need
}
2015-07-15 04:44:58 +02:00
2016-09-21 16:45:29 +02:00
// MNW : SYNC MASTERNODE PAYMENT VOTES FROM OTHER CONNECTED CLIENTS
2016-05-24 21:20:10 +02:00
2016-08-28 12:12:14 +02:00
if ( nRequestedMasternodeAssets = = MASTERNODE_SYNC_MNW ) {
2016-10-22 18:52:14 +02:00
LogPrint ( " mnpayments " , " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastPaymentVote %lld GetTime() %lld diff %lld \n " , nTick , nRequestedMasternodeAssets , nTimeLastPaymentVote , GetTime ( ) , GetTime ( ) - nTimeLastPaymentVote ) ;
2016-08-05 18:25:03 +02:00
// check for timeout first
2016-08-28 12:12:14 +02:00
// This might take a lot longer than MASTERNODE_SYNC_TIMEOUT_SECONDS minutes due to new blocks,
2016-08-05 18:25:03 +02:00
// but that should be OK and it should timeout eventually.
2017-07-03 15:14:07 +02:00
if ( GetTime ( ) - nTimeLastPaymentVote > MASTERNODE_SYNC_TIMEOUT_SECONDS ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout \n " , nTick , nRequestedMasternodeAssets ) ;
2016-08-28 12:12:14 +02:00
if ( nRequestedMasternodeAttempt = = 0 ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- ERROR: failed to sync %s \n " , GetAssetName ( ) ) ;
2016-08-29 21:11:34 +02:00
// probably not a good idea to proceed without winner list
Fail ( ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-08-29 21:11:34 +02:00
return ;
2016-08-28 12:12:14 +02:00
}
SwitchToNextAsset ( ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2015-07-15 04:44:58 +02:00
return ;
}
2016-08-05 18:25:03 +02:00
// check for data
2016-08-28 12:12:14 +02:00
// if mnpayments already has enough blocks and votes, switch to the next asset
// try to fetch data from at least two peers though
2016-09-21 17:32:42 +02:00
if ( nRequestedMasternodeAttempt > 1 & & mnpayments . IsEnoughData ( ) ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- found enough data \n " , nTick , nRequestedMasternodeAssets ) ;
2016-08-28 12:12:14 +02:00
SwitchToNextAsset ( ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-05-29 20:35:09 +02:00
return ;
2015-08-14 05:56:58 +02:00
}
2016-08-05 18:25:03 +02:00
// only request once from each peer
2016-09-27 09:50:04 +02:00
if ( netfulfilledman . HasFulfilledRequest ( pnode - > addr , " masternode-payment-sync " ) ) continue ;
netfulfilledman . AddFulfilledRequest ( pnode - > addr , " masternode-payment-sync " ) ;
2016-02-04 20:29:09 +01:00
2016-08-28 12:12:14 +02:00
if ( pnode - > nVersion < mnpayments . GetMinMasternodePaymentsProto ( ) ) continue ;
nRequestedMasternodeAttempt + + ;
2016-02-04 20:29:09 +01:00
2016-09-21 16:45:29 +02:00
// ask node for all payment votes it has (new nodes will only return votes for future payments)
pnode - > PushMessage ( NetMsgType : : MASTERNODEPAYMENTSYNC , mnpayments . GetStorageLimit ( ) ) ;
2016-09-19 00:23:52 +02:00
// ask node for missing pieces only (old nodes will not be asked)
mnpayments . RequestLowDataPaymentBlocks ( pnode ) ;
2016-02-04 20:29:09 +01:00
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-02-04 23:48:23 +01:00
return ; //this will cause each peer to get one request each six seconds for the various assets we need
}
2016-06-08 08:57:16 +02:00
2016-08-05 18:25:03 +02:00
// GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS
2016-06-08 08:57:16 +02:00
2016-08-28 12:12:14 +02:00
if ( nRequestedMasternodeAssets = = MASTERNODE_SYNC_GOVERNANCE ) {
2017-02-17 21:08:41 +01:00
LogPrint ( " gobject " , " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastGovernanceItem %lld GetTime() %lld diff %lld \n " , nTick , nRequestedMasternodeAssets , nTimeLastGovernanceItem , GetTime ( ) , GetTime ( ) - nTimeLastGovernanceItem ) ;
2016-10-22 18:52:14 +02:00
2016-08-05 18:25:03 +02:00
// check for timeout first
2016-12-06 17:40:37 +01:00
if ( GetTime ( ) - nTimeLastGovernanceItem > MASTERNODE_SYNC_TIMEOUT_SECONDS ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- timeout \n " , nTick , nRequestedMasternodeAssets ) ;
2016-08-28 12:12:14 +02:00
if ( nRequestedMasternodeAttempt = = 0 ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeSync::ProcessTick -- WARNING: failed to sync %s \n " , GetAssetName ( ) ) ;
2016-08-28 12:12:14 +02:00
// it's kind of ok to skip this for now, hopefully we'll catch up later?
}
SwitchToNextAsset ( ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-08-05 18:25:03 +02:00
return ;
}
2016-05-24 21:20:10 +02:00
2017-01-17 21:02:38 +01:00
// only request obj sync once from each peer, then request votes on per-obj basis
if ( netfulfilledman . HasFulfilledRequest ( pnode - > addr , " governance-sync " ) ) {
2017-02-17 21:08:41 +01:00
int nObjsLeftToAsk = governance . RequestGovernanceObjectVotes ( pnode ) ;
static int64_t nTimeNoObjectsLeft = 0 ;
// check for data
if ( nObjsLeftToAsk = = 0 ) {
static int nLastTick = 0 ;
static int nLastVotes = 0 ;
if ( nTimeNoObjectsLeft = = 0 ) {
// asked all objects for votes for the first time
nTimeNoObjectsLeft = GetTime ( ) ;
}
// make sure the condition below is checked only once per tick
if ( nLastTick = = nTick ) continue ;
if ( GetTime ( ) - nTimeNoObjectsLeft > MASTERNODE_SYNC_TIMEOUT_SECONDS & &
governance . GetVoteCount ( ) - nLastVotes < std : : max ( int ( 0.0001 * nLastVotes ) , MASTERNODE_SYNC_TICK_SECONDS )
) {
// We already asked for all objects, waited for MASTERNODE_SYNC_TIMEOUT_SECONDS
// after that and less then 0.01% or MASTERNODE_SYNC_TICK_SECONDS
// (i.e. 1 per second) votes were recieved during the last tick.
// We can be pretty sure that we are done syncing.
LogPrintf ( " CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- asked for all objects, nothing to do \n " , nTick , nRequestedMasternodeAssets ) ;
// reset nTimeNoObjectsLeft to be able to use the same condition on resync
nTimeNoObjectsLeft = 0 ;
SwitchToNextAsset ( ) ;
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2017-02-17 21:08:41 +01:00
return ;
}
nLastTick = nTick ;
nLastVotes = governance . GetVoteCount ( ) ;
}
2017-01-17 21:02:38 +01:00
continue ;
}
2016-09-27 09:50:04 +02:00
netfulfilledman . AddFulfilledRequest ( pnode - > addr , " governance-sync " ) ;
2016-05-24 21:25:33 +02:00
2016-09-28 22:03:54 +02:00
if ( pnode - > nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION ) continue ;
2016-08-28 12:12:14 +02:00
nRequestedMasternodeAttempt + + ;
2016-05-24 21:25:33 +02:00
2017-02-02 09:50:44 +01:00
SendGovernanceSyncRequest ( pnode ) ;
2016-08-05 18:25:03 +02:00
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2016-05-24 21:25:33 +02:00
return ; //this will cause each peer to get one request each six seconds for the various assets we need
}
}
2015-07-15 04:44:58 +02:00
}
2016-12-05 11:06:51 +01:00
// looped through all nodes, release them
2017-03-05 20:16:12 +01:00
ReleaseNodeVector ( vNodesCopy ) ;
2015-07-17 11:17:15 +02:00
}
2016-03-02 22:20:04 +01:00
2017-02-02 09:50:44 +01:00
void CMasternodeSync : : SendGovernanceSyncRequest ( CNode * pnode )
{
if ( pnode - > nVersion > = GOVERNANCE_FILTER_PROTO_VERSION ) {
CBloomFilter filter ;
filter . clear ( ) ;
pnode - > PushMessage ( NetMsgType : : MNGOVERNANCESYNC , uint256 ( ) , filter ) ;
}
else {
pnode - > PushMessage ( NetMsgType : : MNGOVERNANCESYNC , uint256 ( ) ) ;
}
}
2016-03-02 22:20:04 +01:00
void CMasternodeSync : : UpdatedBlockTip ( const CBlockIndex * pindex )
{
pCurrentBlockIndex = pindex ;
}