2016-02-02 16:28:56 +01:00
// Copyright (c) 2014-2016 The Dash Core developers
// 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 ;
LogPrintf ( " CActiveMasternode::ManageState -- %s \n " , 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-17 20:54:28 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageState -- status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetType ( ) , 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-22 18:52:14 +02:00
} else {
2016-10-17 20:54:28 +02:00
ManageStateLocal ( ) ;
2014-12-09 02:17:57 +01:00
}
2016-10-17 20:54:28 +02:00
if ( fPingerEnabled ) {
std : : string strError ;
if ( ! SendMasternodePing ( strError ) ) {
LogPrintf ( " CActiveMasternode::ManageState -- Error on SendMasternodePing(): %s \n " , strError ) ;
}
2015-07-14 07:25:07 +02:00
}
}
2016-08-05 21:49:45 +02:00
std : : string CActiveMasternode : : GetStatus ( )
{
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 " ;
default : return " unknown " ;
2014-12-06 20:41:53 +01:00
}
}
2014-12-09 02:17:57 +01:00
2016-10-17 20:54:28 +02:00
std : : string CActiveMasternode : : GetType ( )
{
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-09-05 18:09:25 +02:00
bool CActiveMasternode : : SendMasternodePing ( std : : string & strErrorRet )
2016-08-05 21:49:45 +02:00
{
2016-10-17 20:54:28 +02:00
if ( vin = = CTxIn ( ) ) {
2015-03-22 00:58:18 +01:00
return false ;
}
2014-12-09 02:17:57 +01:00
2015-04-17 17:10:38 +02:00
CMasternodePing mnp ( vin ) ;
2016-08-05 21:49:45 +02:00
if ( ! mnp . Sign ( keyMasternode , pubKeyMasternode ) ) {
2016-09-05 18:09:25 +02:00
strErrorRet = " Couldn't sign Masternode Ping " ;
2014-12-09 02:17:57 +01:00
return false ;
}
2016-10-17 20:54:28 +02:00
if ( ! mnodeman . Has ( vin ) ) {
strErrorRet = " Masternode List doesn't include our Masternode, shutting down Masternode pinging service! " + vin . ToString ( ) ;
2016-08-05 21:49:45 +02:00
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
2016-09-05 18:09:25 +02:00
strNotCapableReason = strErrorRet ;
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 ) ) {
strErrorRet = " Too early to send Masternode Ping " ;
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-25 16:37:33 +02:00
LogPrint ( " masternode " , " CActiveMasternode::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetType ( ) , fPingerEnabled ) ;
2016-10-17 20:54:28 +02:00
// Check that our local network configuration is correct
if ( ! GetLocal ( service ) ) {
strNotCapableReason = " Can't detect external address. Please consider using the externalip configuration option if problem persists. " ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- not capable: %s \n " , strNotCapableReason ) ;
return ;
}
int mainnetDefaultPort = Params ( CBaseChainParams : : MAIN ) . GetDefaultPort ( ) ;
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
if ( service . GetPort ( ) ! = mainnetDefaultPort ) {
strNotCapableReason = strprintf ( " Invalid port: %u - only %d is supported on mainnet. " , service . GetPort ( ) , mainnetDefaultPort ) ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- not capable: %s \n " , strNotCapableReason ) ;
return ;
}
} else if ( service . GetPort ( ) = = mainnetDefaultPort ) {
strNotCapableReason = strprintf ( " Invalid port: %u - %d is only supported on mainnet. " , service . GetPort ( ) , mainnetDefaultPort ) ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- not capable: %s \n " , strNotCapableReason ) ;
return ;
}
LogPrintf ( " CActiveMasternode::ManageState -- Checking inbound connection to '%s' \n " , service . ToString ( ) ) ;
if ( ! ConnectNode ( ( CAddress ) service , NULL , true ) ) {
strNotCapableReason = " Could not connect to " + service . ToString ( ) ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- not capable: %s \n " , strNotCapableReason ) ;
return ;
}
// Default to REMOTE
eType = MASTERNODE_REMOTE ;
// Check if wallet funds are available
if ( ! pwalletMain ) {
strNotCapableReason = " Wallet not available. " ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- not capable: %s \n " , strNotCapableReason ) ;
return ;
}
if ( pwalletMain - > IsLocked ( ) ) {
strNotCapableReason = " Wallet is locked. " ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- not capable: %s \n " , strNotCapableReason ) ;
return ;
}
if ( pwalletMain - > GetBalance ( ) < 1000 * COIN ) {
strNotCapableReason = " Wallet balance is < 1000 DASH " ;
LogPrintf ( " CActiveMasternode::ManageStateInitial -- not capable: %s \n " , strNotCapableReason ) ;
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 ;
}
LogPrint ( " masternode " , " CActiveMasternode::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetType ( ) , fPingerEnabled ) ;
}
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 " ,
GetStatus ( ) ,
GetType ( ) ,
fPingerEnabled ,
pubKeyMasternode . GetID ( ) . ToString ( ) ) ;
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 " ;
return ;
}
vin = infoMn . vin ;
service = infoMn . addr ;
fPingerEnabled = true ;
if ( ( ( infoMn . nActiveState = = CMasternode : : MASTERNODE_ENABLED ) | |
( infoMn . nActiveState = = CMasternode : : MASTERNODE_PRE_ENABLED ) | |
( infoMn . nActiveState = = CMasternode : : MASTERNODE_WATCHDOG_EXPIRED ) ) ) {
nState = ACTIVE_MASTERNODE_STARTED ;
}
else {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
strNotCapableReason = " Masternode in EXPIRED state " ;
}
}
else {
fPingerEnabled = false ;
strNotCapableReason = " Masternode not in masternode list " ;
nState = ACTIVE_MASTERNODE_NOT_CAPABLE ;
}
}
void CActiveMasternode : : ManageStateLocal ( )
{
LogPrint ( " masternode " , " CActiveMasternode::ManageStateLocal -- status = %s, type = %s, pinger enabled = %d \n " , GetStatus ( ) , GetType ( ) , fPingerEnabled ) ;
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 ;
strNotCapableReason = strprintf ( " %s - %d confirmations " , GetStatus ( ) , nInputAge ) ;
LogPrintf ( " CActiveMasternode::ManageStateLocal -- %s \n " , strNotCapableReason ) ;
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 ) ) {
strNotCapableReason = " Error on CMasternodeBroadcast::Create -- " + strError ;
LogPrintf ( " CActiveMasternode::ManageStateLocal -- %s \n " , strNotCapableReason ) ;
return ;
}
//update to masternode list
LogPrintf ( " CActiveMasternode::ManageStateLocal -- Update Masternode List \n " ) ;
mnodeman . UpdateMasternodeList ( mnb ) ;
//send to all peers
LogPrintf ( " CActiveMasternode::ManageStateLocal -- Relay broadcast, vin=%s \n " , vin . ToString ( ) ) ;
mnb . Relay ( ) ;
fPingerEnabled = true ;
nState = ACTIVE_MASTERNODE_STARTED ;
}
}