2019-01-29 15:53:14 +01:00
// Copyright (c) 2014-2019 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"
2018-11-06 09:54:23 +01:00
# include "evo/deterministicmns.h"
# include "init.h"
2016-01-24 20:05:31 +01:00
# include "masternode-sync.h"
2018-02-12 13:46:38 +01:00
# include "netbase.h"
2016-08-05 21:49:45 +02:00
# include "protocol.h"
2019-01-03 21:08:34 +01:00
# include "validation.h"
2018-02-15 14:33:04 +01:00
# include "warnings.h"
2016-08-05 21:49:45 +02:00
// Keep track of the active Masternode
2018-08-11 21:55:56 +02:00
CActiveMasternodeInfo activeMasternodeInfo ;
2019-01-03 21:08:34 +01:00
CActiveMasternodeManager * activeMasternodeManager ;
2018-02-15 14:33:04 +01:00
2019-01-03 21:08:34 +01:00
std : : string CActiveMasternodeManager : : GetStateString ( ) const
2018-02-15 14:33:04 +01:00
{
switch ( state ) {
2018-11-06 09:54:23 +01:00
case MASTERNODE_WAITING_FOR_PROTX :
return " WAITING_FOR_PROTX " ;
case MASTERNODE_POSE_BANNED :
return " POSE_BANNED " ;
case MASTERNODE_REMOVED :
return " REMOVED " ;
2018-12-10 06:04:13 +01:00
case MASTERNODE_OPERATOR_KEY_CHANGED :
return " OPERATOR_KEY_CHANGED " ;
2018-11-06 09:54:23 +01:00
case MASTERNODE_READY :
return " READY " ;
case MASTERNODE_ERROR :
return " ERROR " ;
default :
return " UNKNOWN " ;
2018-02-15 14:33:04 +01:00
}
}
2019-01-03 21:08:34 +01:00
std : : string CActiveMasternodeManager : : GetStatus ( ) const
2018-02-15 14:33:04 +01:00
{
switch ( state ) {
2018-11-06 09:54:23 +01:00
case MASTERNODE_WAITING_FOR_PROTX :
return " Waiting for ProTx to appear on-chain " ;
case MASTERNODE_POSE_BANNED :
return " Masternode was PoSe banned " ;
case MASTERNODE_REMOVED :
return " Masternode removed from list " ;
2018-12-10 06:04:13 +01:00
case MASTERNODE_OPERATOR_KEY_CHANGED :
return " Operator key changed or revoked " ;
2018-11-06 09:54:23 +01:00
case MASTERNODE_READY :
return " Ready " ;
case MASTERNODE_ERROR :
return " Error. " + strError ;
default :
return " Unknown " ;
2018-02-15 14:33:04 +01:00
}
}
2019-01-03 21:08:34 +01:00
void CActiveMasternodeManager : : Init ( )
2018-02-15 14:33:04 +01:00
{
LOCK ( cs_main ) ;
2018-11-06 09:54:23 +01:00
if ( ! fMasternodeMode ) return ;
2018-02-15 14:33:04 +01:00
2019-01-29 15:54:38 +01:00
if ( ! deterministicMNManager - > IsDIP3Enforced ( ) ) return ;
2018-02-15 14:33:04 +01:00
2018-12-21 16:20:43 +01:00
// Check that our local network configuration is correct
if ( ! fListen ) {
// listen option is probably overwritten by smth else, no good
state = MASTERNODE_ERROR ;
strError = " Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter. " ;
LogPrintf ( " CActiveDeterministicMasternodeManager::Init -- ERROR: %s \n " , strError ) ;
return ;
}
2018-02-15 14:33:04 +01:00
if ( ! GetLocalAddress ( activeMasternodeInfo . service ) ) {
state = MASTERNODE_ERROR ;
return ;
}
CDeterministicMNList mnList = deterministicMNManager - > GetListAtChainTip ( ) ;
2018-10-21 21:45:16 +02:00
CDeterministicMNCPtr dmn = mnList . GetMNByOperatorKey ( * activeMasternodeInfo . blsPubKeyOperator ) ;
2018-02-15 14:33:04 +01:00
if ( ! dmn ) {
// MN not appeared on the chain yet
return ;
}
if ( ! mnList . IsMNValid ( dmn - > proTxHash ) ) {
if ( mnList . IsMNPoSeBanned ( dmn - > proTxHash ) ) {
state = MASTERNODE_POSE_BANNED ;
} else {
state = MASTERNODE_REMOVED ;
}
return ;
}
mnListEntry = dmn ;
2019-01-03 21:08:34 +01:00
LogPrintf ( " CActiveMasternodeManager::Init -- proTxHash=%s, proTx=%s \n " , mnListEntry - > proTxHash . ToString ( ) , mnListEntry - > ToString ( ) ) ;
2018-02-15 14:33:04 +01:00
if ( activeMasternodeInfo . service ! = mnListEntry - > pdmnState - > addr ) {
state = MASTERNODE_ERROR ;
strError = " Local address does not match the address from ProTx " ;
2019-01-03 21:08:34 +01:00
LogPrintf ( " CActiveMasternodeManager::Init -- ERROR: %s " , strError ) ;
2018-02-15 14:33:04 +01:00
return ;
}
2018-12-21 16:20:43 +01:00
if ( Params ( ) . NetworkIDString ( ) ! = CBaseChainParams : : REGTEST ) {
// Check socket connectivity
LogPrintf ( " CActiveDeterministicMasternodeManager::Init -- Checking inbound connection to '%s' \n " , activeMasternodeInfo . service . ToString ( ) ) ;
SOCKET hSocket ;
bool fConnected = ConnectSocket ( activeMasternodeInfo . service , hSocket , nConnectTimeout ) & & IsSelectableSocket ( hSocket ) ;
CloseSocket ( hSocket ) ;
if ( ! fConnected ) {
state = MASTERNODE_ERROR ;
strError = " Could not connect to " + activeMasternodeInfo . service . ToString ( ) ;
LogPrintf ( " CActiveDeterministicMasternodeManager::Init -- ERROR: %s \n " , strError ) ;
return ;
}
}
2018-11-23 16:33:45 +01:00
activeMasternodeInfo . proTxHash = mnListEntry - > proTxHash ;
2018-10-25 16:29:50 +02:00
activeMasternodeInfo . outpoint = mnListEntry - > collateralOutpoint ;
2018-02-15 14:33:04 +01:00
state = MASTERNODE_READY ;
}
2019-01-03 21:08:34 +01:00
void CActiveMasternodeManager : : UpdatedBlockTip ( const CBlockIndex * pindexNew , const CBlockIndex * pindexFork , bool fInitialDownload )
2018-02-15 14:33:04 +01:00
{
LOCK ( cs_main ) ;
2018-11-06 09:54:23 +01:00
if ( ! fMasternodeMode ) return ;
2018-02-15 14:33:04 +01:00
2019-01-29 15:54:38 +01:00
if ( ! deterministicMNManager - > IsDIP3Enforced ( pindexNew - > nHeight ) ) return ;
2018-02-15 14:33:04 +01:00
2018-12-21 16:20:43 +01:00
if ( state = = MASTERNODE_READY ) {
2018-10-25 16:29:50 +02:00
auto mnList = deterministicMNManager - > GetListForBlock ( pindexNew - > GetBlockHash ( ) ) ;
if ( ! mnList . IsMNValid ( mnListEntry - > proTxHash ) ) {
2018-02-15 14:33:04 +01:00
// MN disappeared from MN list
state = MASTERNODE_REMOVED ;
2018-11-23 16:33:45 +01:00
activeMasternodeInfo . proTxHash = uint256 ( ) ;
2018-02-15 14:33:04 +01:00
activeMasternodeInfo . outpoint . SetNull ( ) ;
2018-12-10 06:04:13 +01:00
// MN might have reappeared in same block with a new ProTx
Init ( ) ;
} else if ( mnList . GetMN ( mnListEntry - > proTxHash ) - > pdmnState - > pubKeyOperator ! = mnListEntry - > pdmnState - > pubKeyOperator ) {
// MN operator key changed or revoked
state = MASTERNODE_OPERATOR_KEY_CHANGED ;
activeMasternodeInfo . proTxHash = uint256 ( ) ;
activeMasternodeInfo . outpoint . SetNull ( ) ;
// MN might have reappeared in same block with a new ProTx
2018-02-15 14:33:04 +01:00
Init ( ) ;
}
2018-12-21 16:20:43 +01:00
} else {
// MN might have (re)appeared with a new ProTx or we've found some peers and figured out our local address
2018-02-15 14:33:04 +01:00
Init ( ) ;
}
}
2019-01-03 21:08:34 +01:00
bool CActiveMasternodeManager : : GetLocalAddress ( CService & addrRet )
2018-02-15 14:33:04 +01:00
{
// First try to find whatever local address is specified by externalip option
2019-01-03 10:17:43 +01:00
bool fFoundLocal = GetLocal ( addrRet ) & & IsValidNetAddr ( addrRet ) ;
2018-02-15 14:33:04 +01:00
if ( ! fFoundLocal & & Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : REGTEST ) {
if ( Lookup ( " 127.0.0.1 " , addrRet , GetListenPort ( ) , false ) ) {
fFoundLocal = true ;
}
}
2018-11-06 09:54:23 +01:00
if ( ! fFoundLocal ) {
2018-12-21 16:20:43 +01:00
bool empty = true ;
// If we have some peers, let's try to find our local address from one of them
g_connman - > ForEachNodeContinueIf ( CConnman : : AllNodes , [ & fFoundLocal , & empty ] ( CNode * pnode ) {
empty = false ;
if ( pnode - > addr . IsIPv4 ( ) )
2019-01-03 10:17:43 +01:00
fFoundLocal = GetLocal ( activeMasternodeInfo . service , & pnode - > addr ) & & IsValidNetAddr ( activeMasternodeInfo . service ) ;
2018-12-21 16:20:43 +01:00
return ! fFoundLocal ;
} ) ;
// nothing and no live connections, can't do anything for now
if ( empty ) {
strError = " Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only. " ;
2019-01-03 21:08:34 +01:00
LogPrintf ( " CActiveMasternodeManager::GetLocalAddress -- ERROR: %s \n " , strError ) ;
2018-12-21 16:20:43 +01:00
return false ;
}
2018-02-15 14:33:04 +01:00
}
return true ;
}
2019-01-03 21:08:34 +01:00
bool CActiveMasternodeManager : : IsValidNetAddr ( CService addrIn )
2016-10-17 20:54:28 +02:00
{
2019-01-03 10:17:43 +01:00
// TODO: regtest is fine with any addresses for now,
// should probably be a bit smarter if one day we start to implement tests for this
return Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : REGTEST | |
( addrIn . IsIPv4 ( ) & & IsReachable ( addrIn ) & & addrIn . IsRoutable ( ) ) ;
2016-10-17 20:54:28 +02:00
}