2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
2016-02-02 16:28:56 +01:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2014-12-09 02:17:57 +01:00
# include "activemasternode.h"
2015-04-17 17:10:38 +02:00
# include "masternode.h"
2016-01-24 20:05:31 +01:00
# include "masternode-sync.h"
# include "masternodeman.h"
2016-08-05 21:49:45 +02:00
# include "protocol.h"
extern CWallet * pwalletMain ;
// Keep track of the active Masternode
CActiveMasternode activeMasternode ;
2014-12-09 02:17:57 +01:00
2016-08-05 21:49:45 +02:00
void CActiveMasternode : : ManageState ( )
{
2016-10-17 20:54:28 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageState -- Start \n " ) ;
if ( ! fMasterNode ) {
LogPrint ( " masternode " , " CActiveMasternode::ManageState -- Not a masternode, returning \n " ) ;
return ;
}
2014-12-09 02:17:57 +01:00
2016-02-02 16:28:56 +01:00
if ( Params ( ) . NetworkIDString ( ) ! = CBaseChainParams : : REGTEST & & ! masternodeSync . IsBlockchainSynced ( ) ) {
2016-08-05 21:49:45 +02:00
nState = ACTIVE_MASTERNODE_SYNC_IN_PROCESS ;
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageState -- %s: %s \n " , GetStateString ( ) , GetStatus ( ) ) ;
2014-12-09 02:17:57 +01:00
return ;
}
2016-10-17 20:54:28 +02:00
if ( nState = = ACTIVE_MASTERNODE_SYNC_IN_PROCESS ) {
nState = ACTIVE_MASTERNODE_INITIAL ;
2014-12-09 02:17:57 +01:00
}
2016-10-26 23:21:39 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageState -- status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetTypeString ( ) , fPingerEnabled ) ;
2014-12-09 02:17:57 +01:00
2016-10-17 20:54:28 +02:00
if ( eType = = MASTERNODE_UNKNOWN ) {
ManageStateInitial ( ) ;
}
2015-07-14 07:25:07 +02:00
2016-10-17 20:54:28 +02:00
if ( eType = = MASTERNODE_REMOTE ) {
ManageStateRemote ( ) ;
2016-10-26 23:21:39 +02:00
} else if ( eType = = MASTERNODE_LOCAL ) {
2017-01-01 11:18:21 +01:00
// Try Remote Start first so the started local masternode can be restarted without recreate masternode broadcast.
ManageStateRemote ( ) ;
if ( nState ! = ACTIVE_MASTERNODE_STARTED )
ManageStateLocal ( ) ;
2014-12-09 02:17:57 +01:00
}
2016-10-26 23:21:39 +02:00
SendMasternodePing ( ) ;
}
std : : string CActiveMasternode : : GetStateString ( ) const
{
switch ( nState ) {
case ACTIVE_MASTERNODE_INITIAL : return " INITIAL " ;
case ACTIVE_MASTERNODE_SYNC_IN_PROCESS : return " SYNC_IN_PROCESS " ;
case ACTIVE_MASTERNODE_INPUT_TOO_NEW : return " INPUT_TOO_NEW " ;
case ACTIVE_MASTERNODE_NOT_CAPABLE : return " NOT_CAPABLE " ;
case ACTIVE_MASTERNODE_STARTED : return " STARTED " ;
default : return " UNKNOWN " ;
2015-07-14 07:25:07 +02:00
}
}
2016-10-26 23:21:39 +02:00
std : : string CActiveMasternode : : GetStatus ( ) const
2016-08-05 21:49:45 +02:00
{
switch ( nState ) {
2016-10-22 18:52:14 +02:00
case ACTIVE_MASTERNODE_INITIAL : return " Node just started, not yet activated " ;
2016-08-05 21:49:45 +02:00
case ACTIVE_MASTERNODE_SYNC_IN_PROCESS : return " Sync in progress. Must wait until sync is complete to start Masternode " ;
2016-10-22 18:52:14 +02:00
case ACTIVE_MASTERNODE_INPUT_TOO_NEW : return strprintf ( " Masternode input must have at least %d confirmations " , Params ( ) . GetConsensus ( ) . nMasternodeMinimumConfirmations ) ;
case ACTIVE_MASTERNODE_NOT_CAPABLE : return " Not capable masternode: " + strNotCapableReason ;
case ACTIVE_MASTERNODE_STARTED : return " Masternode successfully started " ;
2016-10-26 23:21:39 +02:00
default : return " Unknown " ;
2014-12-06 20:41:53 +01:00
}
}
2014-12-09 02:17:57 +01:00
2016-10-26 23:21:39 +02:00
std : : string CActiveMasternode : : GetTypeString ( ) const
2016-10-17 20:54:28 +02:00
{
std : : string strType ;
switch ( eType ) {
case MASTERNODE_UNKNOWN :
strType = " UNKNOWN " ;
break ;
case MASTERNODE_REMOTE :
strType = " REMOTE " ;
break ;
case MASTERNODE_LOCAL :
strType = " LOCAL " ;
break ;
default :
strType = " UNKNOWN " ;
break ;
}
return strType ;
}
2016-10-26 23:21:39 +02:00
bool CActiveMasternode : : SendMasternodePing ( )
2016-08-05 21:49:45 +02:00
{
2016-10-26 23:21:39 +02:00
if ( ! fPingerEnabled ) {
2016-11-29 01:01:03 +01:00
LogPrint ( " masternode " , " CActiveMasternode::SendMasternodePing -- %s: masternode ping service is disabled, skipping... \n " , GetStateString ( ) ) ;
2015-03-22 00:58:18 +01:00
return false ;
}
2014-12-09 02:17:57 +01:00
2016-10-26 23:21:39 +02:00
if ( ! mnodeman . Has ( vin ) ) {
strNotCapableReason = " Masternode not in masternode list " ;
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
LogPrintf ( " CActiveMasternode::SendMasternodePing -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2014-12-09 02:17:57 +01:00
return false ;
}
2016-10-26 23:21:39 +02:00
CMasternodePing mnp ( vin ) ;
if ( ! mnp . Sign ( keyMasternode , pubKeyMasternode ) ) {
LogPrintf ( " CActiveMasternode::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping \n " ) ;
2014-12-09 02:17:57 +01:00
return false ;
}
2016-10-17 20:54:28 +02:00
// Update lastPing for our masternode in Masternode list
if ( mnodeman . IsMasternodePingedWithin ( vin , MASTERNODE_MIN_MNP_SECONDS , mnp . sigTime ) ) {
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::SendMasternodePing -- Too early to send Masternode Ping \n " ) ;
2016-10-17 20:54:28 +02:00
return false ;
}
mnodeman . SetMasternodeLastPing ( vin , mnp ) ;
LogPrintf ( " CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s \n " , vin . ToString ( ) ) ;
mnp . Relay ( ) ;
return true ;
2014-12-06 20:41:53 +01:00
}
2016-10-17 20:54:28 +02:00
void CActiveMasternode : : ManageStateInitial ( )
{
2016-10-26 23:21:39 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetTypeString ( ) , fPingerEnabled ) ;
2016-12-15 17:27:24 +01:00
2016-10-17 20:54:28 +02:00
// Check that our local network configuration is correct
2016-12-15 17:27:24 +01:00
if ( ! fListen ) {
// listen option is probably overwritten by smth else, no good
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
strNotCapableReason = " Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter. " ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
return ;
}
bool fFoundLocal = false ;
{
LOCK ( cs_vNodes ) ;
// First try to find whatever local address is specified by externalip option
fFoundLocal = GetLocal ( service ) & & CMasternode : : IsValidNetAddr ( service ) ;
if ( ! fFoundLocal ) {
// nothing and no live connections, can't do anything for now
if ( vNodes . empty ( ) ) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
strNotCapableReason = " Can't detect valid external address. Will retry when there are some connections available. " ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
return ;
}
// We have some peers, let's try to find our local address from one of them
BOOST_FOREACH ( CNode * pnode , vNodes ) {
if ( pnode - > fSuccessfullyConnected & & pnode - > addr . IsIPv4 ( ) ) {
fFoundLocal = GetLocal ( service , & pnode - > addr ) & & CMasternode : : IsValidNetAddr ( service ) ;
if ( fFoundLocal ) break ;
}
}
}
}
if ( ! fFoundLocal ) {
2016-10-26 23:21:39 +02:00
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
2016-12-15 17:27:24 +01:00
strNotCapableReason = " Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only. " ;
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
return ;
}
int mainnetDefaultPort = Params ( CBaseChainParams : : MAIN ) . GetDefaultPort ( ) ;
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
if ( service . GetPort ( ) ! = mainnetDefaultPort ) {
2016-10-26 23:21:39 +02:00
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
2016-10-17 20:54:28 +02:00
strNotCapableReason = strprintf ( " Invalid port: %u - only %d is supported on mainnet. " , service . GetPort ( ) , mainnetDefaultPort ) ;
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
return ;
}
} else if ( service . GetPort ( ) = = mainnetDefaultPort ) {
2016-10-26 23:21:39 +02:00
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
2016-10-17 20:54:28 +02:00
strNotCapableReason = strprintf ( " Invalid port: %u - %d is only supported on mainnet. " , service . GetPort ( ) , mainnetDefaultPort ) ;
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
return ;
}
2016-12-15 17:27:24 +01:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- Checking inbound connection to '%s' \n " , service . ToString ( ) ) ;
2016-10-17 20:54:28 +02:00
if ( ! ConnectNode ( ( CAddress ) service , NULL , true ) ) {
2016-10-26 23:21:39 +02:00
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
2016-10-17 20:54:28 +02:00
strNotCapableReason = " Could not connect to " + service . ToString ( ) ;
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
return ;
}
// Default to REMOTE
eType = MASTERNODE_REMOTE ;
// Check if wallet funds are available
if ( ! pwalletMain ) {
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: Wallet not available \n " , GetStateString ( ) ) ;
2016-10-17 20:54:28 +02:00
return ;
}
if ( pwalletMain - > IsLocked ( ) ) {
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: Wallet is locked \n " , GetStateString ( ) ) ;
2016-10-17 20:54:28 +02:00
return ;
}
if ( pwalletMain - > GetBalance ( ) < 1000 * COIN ) {
2016-11-30 02:33:47 +01:00
LogPrintf ( " CActiveMasternode::ManageStateInitial -- %s: Wallet balance is < 1000 DASH \n " , GetStateString ( ) ) ;
2016-10-17 20:54:28 +02:00
return ;
}
// Choose coins to use
CPubKey pubKeyCollateral ;
CKey keyCollateral ;
// If collateral is found switch to LOCAL mode
if ( pwalletMain - > GetMasternodeVinAndKeys ( vin , pubKeyCollateral , keyCollateral ) ) {
eType = MASTERNODE_LOCAL ;
}
2016-10-26 23:21:39 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetTypeString ( ) , fPingerEnabled ) ;
2016-10-17 20:54:28 +02:00
}
void CActiveMasternode : : ManageStateRemote ( )
{
2016-10-25 16:37:33 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, pubKeyMasternode.GetID() = %s \n " ,
2016-10-26 23:21:39 +02:00
GetStatus ( ) , fPingerEnabled , GetTypeString ( ) , pubKeyMasternode . GetID ( ) . ToString ( ) ) ;
2016-10-25 16:37:33 +02:00
2016-10-17 20:54:28 +02:00
mnodeman . CheckMasternode ( pubKeyMasternode ) ;
masternode_info_t infoMn = mnodeman . GetMasternodeInfo ( pubKeyMasternode ) ;
if ( infoMn . fInfoValid ) {
if ( infoMn . nProtocolVersion ! = PROTOCOL_VERSION ) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
strNotCapableReason = " Invalid protocol version " ;
2016-10-26 23:21:39 +02:00
LogPrintf ( " CActiveMasternode::ManageStateRemote -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
return ;
}
if ( service ! = infoMn . addr ) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
strNotCapableReason = " Specified IP doesn't match our external address. " ;
LogPrintf ( " CActiveMasternode::ManageStateRemote -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
return ;
}
2016-12-24 03:49:13 +01:00
if ( ! CMasternode : : IsValidStateForAutoStart ( infoMn . nActiveState ) ) {
2016-10-17 20:54:28 +02:00
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
2016-10-26 23:21:39 +02:00
strNotCapableReason = strprintf ( " Masternode in %s state " , CMasternode : : StateToString ( infoMn . nActiveState ) ) ;
LogPrintf ( " CActiveMasternode::ManageStateRemote -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-12-24 03:49:13 +01:00
return ;
}
if ( nState ! = ACTIVE_MASTERNODE_STARTED ) {
LogPrintf ( " CActiveMasternode::ManageStateRemote -- STARTED! \n " ) ;
vin = infoMn . vin ;
service = infoMn . addr ;
fPingerEnabled = true ;
nState = ACTIVE_MASTERNODE_STARTED ;
2016-10-17 20:54:28 +02:00
}
}
else {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
2016-10-26 23:21:39 +02:00
strNotCapableReason = " Masternode not in masternode list " ;
LogPrintf ( " CActiveMasternode::ManageStateRemote -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
}
}
void CActiveMasternode : : ManageStateLocal ( )
{
2016-10-26 23:21:39 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageStateLocal -- status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetTypeString ( ) , fPingerEnabled ) ;
2016-10-17 20:54:28 +02:00
if ( nState = = ACTIVE_MASTERNODE_STARTED ) {
return ;
}
// Choose coins to use
CPubKey pubKeyCollateral ;
CKey keyCollateral ;
if ( pwalletMain - > GetMasternodeVinAndKeys ( vin , pubKeyCollateral , keyCollateral ) ) {
int nInputAge = GetInputAge ( vin ) ;
if ( nInputAge < Params ( ) . GetConsensus ( ) . nMasternodeMinimumConfirmations ) {
nState = ACTIVE_MASTERNODE_INPUT_TOO_NEW ;
2016-10-26 23:21:39 +02:00
strNotCapableReason = strprintf ( _ ( " %s - %d confirmations " ) , GetStatus ( ) , nInputAge ) ;
LogPrintf ( " CActiveMasternode::ManageStateLocal -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
return ;
}
{
LOCK ( pwalletMain - > cs_wallet ) ;
pwalletMain - > LockCoin ( vin . prevout ) ;
}
CMasternodeBroadcast mnb ;
std : : string strError ;
if ( ! CMasternodeBroadcast : : Create ( vin , service , keyCollateral , pubKeyCollateral , keyMasternode , pubKeyMasternode , strError , mnb ) ) {
2016-10-26 23:21:39 +02:00
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
strNotCapableReason = " Error creating mastenode broadcast: " + strError ;
LogPrintf ( " CActiveMasternode::ManageStateLocal -- %s: %s \n " , GetStateString ( ) , strNotCapableReason ) ;
2016-10-17 20:54:28 +02:00
return ;
}
2016-12-24 03:49:13 +01:00
fPingerEnabled = true ;
nState = ACTIVE_MASTERNODE_STARTED ;
2016-10-17 20:54:28 +02:00
//update to masternode list
LogPrintf ( " CActiveMasternode::ManageStateLocal -- Update Masternode List \n " ) ;
mnodeman . UpdateMasternodeList ( mnb ) ;
2016-11-13 18:52:34 +01:00
mnodeman . NotifyMasternodeUpdates ( ) ;
2016-10-17 20:54:28 +02:00
//send to all peers
LogPrintf ( " CActiveMasternode::ManageStateLocal -- Relay broadcast, vin=%s \n " , vin . ToString ( ) ) ;
mnb . Relay ( ) ;
}
}