2015-07-15 04:44:58 +02:00
// Copyright (c) 2014-2015 The Dash developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# include "main.h"
2015-07-29 05:26:08 +02:00
# include "activemasternode.h"
2015-07-15 04:44:58 +02:00
# include "masternode-sync.h"
2015-07-19 01:20:48 +02:00
# include "masternode-payments.h"
2015-07-25 18:29:29 +02:00
# include "masternode-budget.h"
2015-07-15 04:44:58 +02:00
# include "masternode.h"
2015-07-17 11:17:15 +02:00
# include "masternodeman.h"
2015-07-15 04:44:58 +02:00
# include "util.h"
# include "addrman.h"
class CMasternodeSync ;
CMasternodeSync masternodeSync ;
CMasternodeSync : : CMasternodeSync ( )
{
lastMasternodeList = 0 ;
lastMasternodeWinner = 0 ;
lastBudgetItem = 0 ;
2015-07-29 06:16:11 +02:00
lastFailure = 0 ;
nCountFailures = 0 ;
sumMasternodeList = 0 ;
sumMasternodeWinner = 0 ;
sumBudgetItemProp = 0 ;
sumBudgetItemFin = 0 ;
countMasternodeList = 0 ;
countMasternodeWinner = 0 ;
countBudgetItemProp = 0 ;
countBudgetItemFin = 0 ;
2015-07-17 12:26:24 +02:00
RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL ;
2015-07-15 04:44:58 +02:00
RequestedMasternodeAttempt = 0 ;
}
bool CMasternodeSync : : IsSynced ( )
{
2015-07-23 03:53:17 +02:00
return RequestedMasternodeAssets = = MASTERNODE_SYNC_FINISHED ;
2015-07-15 04:44:58 +02:00
}
2015-07-26 22:04:17 +02:00
bool CMasternodeSync : : IsBlockchainSynced ( )
2015-07-26 21:37:01 +02:00
{
2015-07-26 22:04:17 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( pindexPrev = = NULL ) return false ;
2015-07-28 22:07:40 +02:00
if ( pindexPrev - > nTime + 600 < GetTime ( ) ) return false ;
2015-07-26 22:04:17 +02:00
return true ;
2015-07-26 21:37:01 +02:00
}
2015-07-15 04:44:58 +02:00
void CMasternodeSync : : AddedMasternodeList ( )
{
lastMasternodeList = GetTime ( ) ;
}
void CMasternodeSync : : AddedMasternodeWinner ( )
{
lastMasternodeWinner = GetTime ( ) ;
}
void CMasternodeSync : : AddedBudgetItem ( )
{
lastBudgetItem = GetTime ( ) ;
}
2015-07-29 10:08:15 +02:00
bool CMasternodeSync : : IsBudgetPropEmpty ( )
{
return sumBudgetItemProp = = 0 & & countBudgetItemProp > 0 ;
}
2015-07-29 10:06:30 +02:00
bool CMasternodeSync : : IsBudgetFinEmpty ( )
{
return sumBudgetItemFin = = 0 & & countBudgetItemFin > 0 ;
}
2015-07-15 04:44:58 +02:00
void CMasternodeSync : : GetNextAsset ( )
{
switch ( RequestedMasternodeAssets )
{
2015-07-17 12:26:24 +02:00
case ( MASTERNODE_SYNC_INITIAL ) :
2015-07-25 18:29:29 +02:00
case ( MASTERNODE_SYNC_FAILED ) :
2015-07-19 01:25:52 +02:00
lastMasternodeList = 0 ;
lastMasternodeWinner = 0 ;
lastBudgetItem = 0 ;
2015-07-29 10:06:30 +02:00
lastFailure = 0 ;
nCountFailures = 0 ;
sumMasternodeList = 0 ;
sumMasternodeWinner = 0 ;
sumBudgetItemProp = 0 ;
sumBudgetItemFin = 0 ;
countMasternodeList = 0 ;
countMasternodeWinner = 0 ;
countBudgetItemProp = 0 ;
countBudgetItemFin = 0 ;
2015-07-17 12:26:24 +02:00
RequestedMasternodeAssets = MASTERNODE_SYNC_SPORKS ;
2015-07-30 10:51:48 +02:00
ClearFulfilledRequest ( ) ;
2015-07-17 05:03:42 +02:00
break ;
2015-07-17 12:26:24 +02:00
case ( MASTERNODE_SYNC_SPORKS ) :
2015-07-15 04:44:58 +02:00
RequestedMasternodeAssets = MASTERNODE_SYNC_LIST ;
break ;
case ( MASTERNODE_SYNC_LIST ) :
RequestedMasternodeAssets = MASTERNODE_SYNC_MNW ;
break ;
case ( MASTERNODE_SYNC_MNW ) :
RequestedMasternodeAssets = MASTERNODE_SYNC_BUDGET ;
break ;
case ( MASTERNODE_SYNC_BUDGET ) :
2015-07-19 17:49:46 +02:00
LogPrintf ( " CMasternodeSync::GetNextAsset - Sync has finished \n " ) ;
2015-07-17 12:26:24 +02:00
RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED ;
2015-07-15 04:44:58 +02:00
break ;
}
2015-07-17 11:17:15 +02:00
RequestedMasternodeAttempt = 0 ;
2015-07-15 04:44:58 +02:00
}
2015-07-29 06:16:11 +02:00
void CMasternodeSync : : ProcessMessage ( CNode * pfrom , std : : string & strCommand , CDataStream & vRecv )
{
if ( strCommand = = " ssc " ) { //Sync status count
int nItemID ;
int nCount ;
vRecv > > nItemID > > nCount ;
if ( RequestedMasternodeAssets > = MASTERNODE_SYNC_FINISHED ) return ;
2015-07-29 10:06:30 +02:00
//this means we will receive no further communication
switch ( nItemID )
{
case ( MASTERNODE_SYNC_LIST ) :
if ( nItemID ! = RequestedMasternodeAssets ) return ;
if ( nCount = = 0 ) lastMasternodeList = GetTime ( ) ;
sumMasternodeList + = nCount ;
countMasternodeList + + ;
break ;
case ( MASTERNODE_SYNC_MNW ) :
if ( nItemID ! = RequestedMasternodeAssets ) return ;
if ( nCount = = 0 ) lastMasternodeWinner = GetTime ( ) ;
sumMasternodeWinner + = nCount ;
countMasternodeWinner + + ;
break ;
case ( MASTERNODE_SYNC_BUDGET_PROP ) :
if ( RequestedMasternodeAssets ! = MASTERNODE_SYNC_BUDGET ) return ;
if ( nCount = = 0 ) lastBudgetItem = GetTime ( ) ;
sumBudgetItemProp + = nCount ;
countBudgetItemProp + + ;
break ;
case ( MASTERNODE_SYNC_BUDGET_FIN ) :
if ( RequestedMasternodeAssets ! = MASTERNODE_SYNC_BUDGET ) return ;
if ( nCount = = 0 ) lastBudgetItem = GetTime ( ) ;
sumBudgetItemFin + = nCount ;
countBudgetItemFin + + ;
break ;
2015-07-29 06:16:11 +02:00
}
2015-07-30 10:51:48 +02:00
LogPrintf ( " CMasternodeSync:ProcessMessage - ssc - got inventory count %d %d \n " , nItemID , nCount ) ;
}
}
void CMasternodeSync : : ClearFulfilledRequest ( )
{
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes )
{
pnode - > ClearFulfilledRequest ( " getspork " ) ;
pnode - > ClearFulfilledRequest ( " mnsync " ) ;
pnode - > ClearFulfilledRequest ( " mnwsync " ) ;
pnode - > ClearFulfilledRequest ( " busync " ) ;
2015-07-29 06:16:11 +02:00
}
}
2015-07-17 11:17:15 +02:00
void CMasternodeSync : : Process ( )
2015-07-15 04:44:58 +02:00
{
2015-07-19 10:19:54 +02:00
static int tick = 0 ;
if ( tick + + % MASTERNODE_SYNC_TIMEOUT ! = 0 ) return ;
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( pindexPrev = = NULL ) return ;
2015-07-17 11:17:15 +02:00
2015-07-18 01:49:41 +02:00
if ( IsSynced ( ) ) {
/*
Resync if we lose all masternodes from sleep / wake or failure to sync originally
*/
if ( mnodeman . CountEnabled ( ) = = 0 ) {
2015-07-30 10:51:48 +02:00
ClearFulfilledRequest ( ) ;
2015-07-18 01:49:41 +02:00
RequestedMasternodeAssets = MASTERNODE_SYNC_INITIAL ;
2015-07-19 10:19:54 +02:00
} else
return ;
2015-07-18 01:49:41 +02:00
}
2015-07-15 04:44:58 +02:00
2015-07-25 18:29:29 +02:00
//try syncing again in an hour
if ( RequestedMasternodeAssets = = MASTERNODE_SYNC_FAILED & & lastFailure + ( 60 * 60 ) < GetTime ( ) ) {
GetNextAsset ( ) ;
} else if ( RequestedMasternodeAssets = = MASTERNODE_SYNC_FAILED ) {
return ;
}
2015-07-19 10:19:54 +02:00
if ( fDebug ) LogPrintf ( " CMasternodeSync::Process() - tick %d RequestedMasternodeAssets %d \n " , tick , RequestedMasternodeAssets ) ;
2015-07-17 11:17:15 +02:00
2015-07-17 12:26:24 +02:00
if ( RequestedMasternodeAssets = = MASTERNODE_SYNC_INITIAL ) GetNextAsset ( ) ;
2015-07-15 04:44:58 +02:00
2015-07-17 11:17:15 +02:00
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes )
{
2015-07-23 23:35:14 +02:00
if ( Params ( ) . NetworkID ( ) = = CBaseChainParams : : REGTEST ) {
if ( RequestedMasternodeAttempt < = 2 ) {
2015-07-23 01:51:51 +02:00
pnode - > PushMessage ( " getsporks " ) ; //get current network sporks
2015-07-23 23:35:14 +02:00
} else if ( RequestedMasternodeAttempt < 4 ) {
mnodeman . DsegUpdate ( pnode ) ;
} else if ( RequestedMasternodeAttempt < 6 ) {
int nMnCount = mnodeman . CountEnabled ( ) * 2 ;
pnode - > PushMessage ( " mnget " , nMnCount ) ; //sync payees
uint256 n = 0 ;
pnode - > PushMessage ( " mnvs " , n ) ; //sync masternode votes
} else {
RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED ;
2015-07-17 11:17:15 +02:00
}
2015-07-23 23:35:14 +02:00
RequestedMasternodeAttempt + + ;
2015-07-19 01:25:52 +02:00
return ;
}
2015-07-23 23:35:14 +02:00
//set to synced
if ( RequestedMasternodeAssets = = MASTERNODE_SYNC_SPORKS ) {
if ( pnode - > HasFulfilledRequest ( " getspork " ) ) continue ;
pnode - > FulfilledRequest ( " getspork " ) ;
pnode - > PushMessage ( " getsporks " ) ; //get current network sporks
if ( RequestedMasternodeAttempt > = 2 ) GetNextAsset ( ) ;
RequestedMasternodeAttempt + + ;
return ;
}
2015-07-20 20:56:02 +02:00
2015-07-24 00:32:29 +02:00
if ( IsInitialBlockDownload ( ) ) return ;
2015-07-19 10:19:54 +02:00
//don't begin syncing until we're almost at a recent block
2015-07-28 22:07:40 +02:00
if ( pindexPrev - > nTime + 600 < GetTime ( ) ) return ;
2015-07-15 04:44:58 +02:00
2015-07-20 07:03:36 +02:00
if ( pnode - > nVersion > = masternodePayments . GetMinMasternodePaymentsProto ( ) ) {
2015-07-15 04:44:58 +02:00
2015-07-19 01:25:52 +02:00
if ( RequestedMasternodeAssets = = MASTERNODE_SYNC_LIST ) {
if ( fDebug ) LogPrintf ( " CMasternodeSync::Process() - lastMasternodeList %lld (GetTime() - MASTERNODE_SYNC_TIMEOUT) %lld \n " , lastMasternodeList , GetTime ( ) - MASTERNODE_SYNC_TIMEOUT ) ;
2015-07-27 05:41:25 +02:00
if ( lastMasternodeList > 0 & & lastMasternodeList < GetTime ( ) - MASTERNODE_SYNC_TIMEOUT & & RequestedMasternodeAttempt > = 4 ) { //hasn't received a new item in the last five seconds, so we'll move to the
2015-07-17 11:17:15 +02:00
GetNextAsset ( ) ;
2015-07-15 04:44:58 +02:00
return ;
}
2015-07-17 11:17:15 +02:00
if ( pnode - > HasFulfilledRequest ( " mnsync " ) ) continue ;
pnode - > FulfilledRequest ( " mnsync " ) ;
2015-07-15 04:44:58 +02:00
2015-07-27 05:41:25 +02:00
mnodeman . DsegUpdate ( pnode ) ;
RequestedMasternodeAttempt + + ;
2015-07-17 11:17:15 +02:00
return ;
}
2015-07-15 04:44:58 +02:00
2015-07-19 01:25:52 +02:00
if ( RequestedMasternodeAssets = = MASTERNODE_SYNC_MNW ) {
2015-07-27 05:41:25 +02:00
if ( lastMasternodeWinner > 0 & & lastMasternodeWinner < GetTime ( ) - MASTERNODE_SYNC_TIMEOUT & & RequestedMasternodeAttempt > = 4 ) { //hasn't received a new item in the last five seconds, so we'll move to the
2015-07-17 11:17:15 +02:00
GetNextAsset ( ) ;
2015-07-15 04:44:58 +02:00
return ;
}
2015-07-17 11:17:15 +02:00
if ( pnode - > HasFulfilledRequest ( " mnwsync " ) ) continue ;
pnode - > FulfilledRequest ( " mnwsync " ) ;
2015-07-21 04:24:43 +02:00
2015-07-27 05:41:25 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( pindexPrev = = NULL ) return ;
int nMnCount = mnodeman . CountEnabled ( ) * 2 ;
pnode - > PushMessage ( " mnget " , nMnCount ) ; //sync payees
RequestedMasternodeAttempt + + ;
2015-07-21 04:24:43 +02:00
2015-07-17 11:17:15 +02:00
return ;
}
2015-07-19 01:25:52 +02:00
}
if ( pnode - > nVersion > = MIN_BUDGET_PEER_PROTO_VERSION ) {
2015-07-17 11:17:15 +02:00
if ( RequestedMasternodeAssets = = MASTERNODE_SYNC_BUDGET ) {
2015-07-26 16:01:49 +02:00
//we'll start rejecting votes if we accidentally get set as synced too soon
2015-07-29 06:16:11 +02:00
if ( lastBudgetItem > 0 & & lastBudgetItem < GetTime ( ) - MASTERNODE_SYNC_TIMEOUT & & RequestedMasternodeAttempt > = 4 ) { //hasn't received a new item in the last five seconds, so we'll move to the
2015-07-30 10:51:48 +02:00
LogPrintf ( " CMasternodeSync::Process - HasNextFinalizedBudget %d nCountFailures %d IsBudgetPropEmpty %d \n " , budget . HasNextFinalizedBudget ( ) , nCountFailures , IsBudgetPropEmpty ( ) ) ;
2015-07-29 10:08:15 +02:00
if ( budget . HasNextFinalizedBudget ( ) | | nCountFailures > = 2 | | IsBudgetPropEmpty ( ) ) {
2015-07-25 18:29:29 +02:00
GetNextAsset ( ) ;
2015-07-29 05:26:08 +02:00
//try to activate our masternode if possible
activeMasternode . ManageStatus ( ) ;
2015-07-25 18:29:29 +02:00
} else { //we've failed to sync, this state will reject the next budget block
LogPrintf ( " CMasternodeSync::Process - ERROR - Sync has failed, will retry later \n " ) ;
RequestedMasternodeAssets = MASTERNODE_SYNC_FAILED ;
RequestedMasternodeAttempt = 0 ;
lastFailure = GetTime ( ) ;
2015-07-28 22:14:32 +02:00
nCountFailures + + ;
2015-07-25 18:29:29 +02:00
}
2015-07-15 04:44:58 +02:00
return ;
}
2015-07-17 11:17:15 +02:00
if ( pnode - > HasFulfilledRequest ( " busync " ) ) continue ;
pnode - > FulfilledRequest ( " busync " ) ;
2015-07-27 05:41:25 +02:00
uint256 n = 0 ;
pnode - > PushMessage ( " mnvs " , n ) ; //sync masternode votes
RequestedMasternodeAttempt + + ;
2015-07-17 11:17:15 +02:00
return ;
2015-07-15 04:44:58 +02:00
}
2015-07-17 11:17:15 +02:00
2015-07-15 04:44:58 +02:00
}
}
2015-07-17 11:17:15 +02:00
}