neobytes/src/activemasternode.cpp
UdjinM6 a4ff2a19a7
Fix some warnings and do a couple of other trivial cleanups (#2315)
* Fix various warnings

* A couple of trivial cleanups

* fix 2320
2018-09-28 10:55:11 +03:00

407 lines
18 KiB
C++

// Copyright (c) 2014-2017 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "activemasternode.h"
#include "masternode.h"
#include "masternode-sync.h"
#include "masternodeman.h"
#include "netbase.h"
#include "protocol.h"
#include "netbase.h"
#include "warnings.h"
#include "init.h"
#include "evo/deterministicmns.h"
// Keep track of the active Masternode
CActiveMasternodeInfo activeMasternodeInfo;
CActiveLegacyMasternodeManager legacyActiveMasternodeManager;
CActiveDeterministicMasternodeManager* activeMasternodeManager;
std::string CActiveDeterministicMasternodeManager::GetStateString() const
{
switch (state) {
case MASTERNODE_WAITING_FOR_PROTX: return "WAITING_FOR_PROTX";
case MASTERNODE_POSE_BANNED: return "POSE_BANNED";
case MASTERNODE_REMOVED: return "REMOVED";
case MASTERNODE_READY: return "READY";
case MASTERNODE_ERROR: return "ERROR";
default: return "UNKNOWN";
}
}
std::string CActiveDeterministicMasternodeManager::GetStatus() const
{
switch (state) {
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";
case MASTERNODE_READY: return "Ready";
case MASTERNODE_ERROR: return "Error. " + strError;
default: return "Unknown";
}
}
void CActiveDeterministicMasternodeManager::Init()
{
LOCK(cs_main);
if (!fMasternodeMode)
return;
if (!deterministicMNManager->IsDeterministicMNsSporkActive())
return;
if (!GetLocalAddress(activeMasternodeInfo.service)) {
state = MASTERNODE_ERROR;
return;
}
CDeterministicMNList mnList = deterministicMNManager->GetListAtChainTip();
CDeterministicMNCPtr dmn = mnList.GetMNByOperatorKey(activeMasternodeInfo.keyIDOperator);
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;
LogPrintf("CActiveDeterministicMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", mnListEntry->proTxHash.ToString(), mnListEntry->ToString());
if (activeMasternodeInfo.service != mnListEntry->pdmnState->addr) {
state = MASTERNODE_ERROR;
strError = "Local address does not match the address from ProTx";
LogPrintf("CActiveDeterministicMasternodeManager::Init -- ERROR: %s", strError);
return;
}
if (mnListEntry->pdmnState->nProtocolVersion != PROTOCOL_VERSION) {
state = MASTERNODE_ERROR;
strError = "Local protocol version does not match version from ProTx. You may need to update the ProTx";
LogPrintf("CActiveDeterministicMasternodeManager::Init -- ERROR: %s", strError);
return;
}
activeMasternodeInfo.outpoint = COutPoint(mnListEntry->proTxHash, mnListEntry->nCollateralIndex);
state = MASTERNODE_READY;
}
void CActiveDeterministicMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
{
LOCK(cs_main);
if (!fMasternodeMode)
return;
if (!deterministicMNManager->IsDeterministicMNsSporkActive(pindexNew->nHeight)) {
return;
}
if (state == MASTERNODE_WAITING_FOR_PROTX) {
Init();
} else if (state == MASTERNODE_READY) {
if (!deterministicMNManager->HasValidMNAtBlock(pindexNew->GetBlockHash(), mnListEntry->proTxHash)) {
// MN disappeared from MN list
state = MASTERNODE_REMOVED;
activeMasternodeInfo.outpoint.SetNull();
// MN might have reappeared in same block with a new ProTx (with same masternode key)
Init();
}
} else if (state == MASTERNODE_REMOVED || state == MASTERNODE_POSE_BANNED) {
// MN might have reappeared with a new ProTx (with same masternode key)
Init();
}
}
bool CActiveDeterministicMasternodeManager::GetLocalAddress(CService &addrRet)
{
// First try to find whatever local address is specified by externalip option
bool fFoundLocal = GetLocal(addrRet) && CMasternode::IsValidNetAddr(addrRet);
if (!fFoundLocal && Params().NetworkIDString() == CBaseChainParams::REGTEST) {
if (Lookup("127.0.0.1", addrRet, GetListenPort(), false)) {
fFoundLocal = true;
}
}
if(!fFoundLocal) {
strError = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
LogPrintf("CActiveDeterministicMasternodeManager::GetLocalAddress -- ERROR: %s\n", strError);
return false;
}
return true;
}
/********* LEGACY *********/
void CActiveLegacyMasternodeManager::ManageState(CConnman& connman)
{
if (deterministicMNManager->IsDeterministicMNsSporkActive())
return;
LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageState -- Start\n");
if(!fMasternodeMode) {
LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageState -- Not a masternode, returning\n");
return;
}
if(Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
nState = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
LogPrintf("CActiveLegacyMasternodeManager::ManageState -- %s: %s\n", GetStateString(), GetStatus());
return;
}
if(nState == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) {
nState = ACTIVE_MASTERNODE_INITIAL;
}
LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageState -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
if(eType == MASTERNODE_UNKNOWN) {
ManageStateInitial(connman);
}
if(eType == MASTERNODE_REMOTE) {
ManageStateRemote();
}
SendMasternodePing(connman);
}
std::string CActiveLegacyMasternodeManager::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";
}
}
std::string CActiveLegacyMasternodeManager::GetStatus() const
{
switch (nState) {
case ACTIVE_MASTERNODE_INITIAL: return "Node just started, not yet activated";
case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "Sync in progress. Must wait until sync is complete to start Masternode";
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";
}
}
std::string CActiveLegacyMasternodeManager::GetTypeString() const
{
std::string strType;
switch(eType) {
case MASTERNODE_REMOTE:
strType = "REMOTE";
break;
default:
strType = "UNKNOWN";
break;
}
return strType;
}
bool CActiveLegacyMasternodeManager::SendMasternodePing(CConnman& connman)
{
if (deterministicMNManager->IsDeterministicMNsSporkActive())
return false;
if(!fPingerEnabled) {
LogPrint("masternode", "CActiveLegacyMasternodeManager::SendMasternodePing -- %s: masternode ping service is disabled, skipping...\n", GetStateString());
return false;
}
if(!mnodeman.Has(activeMasternodeInfo.outpoint)) {
strNotCapableReason = "Masternode not in masternode list";
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- %s: %s\n", GetStateString(), strNotCapableReason);
return false;
}
CMasternodePing mnp(activeMasternodeInfo.outpoint);
mnp.nSentinelVersion = nSentinelVersion;
mnp.fSentinelIsCurrent =
(abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_SENTINEL_PING_MAX_SECONDS);
if(!mnp.Sign(activeMasternodeInfo.keyOperator, activeMasternodeInfo.keyIDOperator)) {
LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
return false;
}
// Update lastPing for our masternode in Masternode list
if(mnodeman.IsMasternodePingedWithin(activeMasternodeInfo.outpoint, MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- Too early to send Masternode Ping\n");
return false;
}
mnodeman.SetMasternodeLastPing(activeMasternodeInfo.outpoint, mnp);
LogPrintf("CActiveLegacyMasternodeManager::SendMasternodePing -- Relaying ping, collateral=%s\n", activeMasternodeInfo.outpoint.ToStringShort());
mnp.Relay(connman);
return true;
}
bool CActiveLegacyMasternodeManager::UpdateSentinelPing(int version)
{
nSentinelVersion = version;
nSentinelPingTime = GetAdjustedTime();
return true;
}
void CActiveLegacyMasternodeManager::ManageStateInitial(CConnman& connman)
{
if (deterministicMNManager->IsDeterministicMNsSporkActive())
return;
LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
// Check that our local network configuration is correct
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("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
// First try to find whatever local address is specified by externalip option
bool fFoundLocal = GetLocal(activeMasternodeInfo.service) && CMasternode::IsValidNetAddr(activeMasternodeInfo.service);
if(!fFoundLocal) {
bool empty = true;
// If we have some peers, let's try to find our local address from one of them
connman.ForEachNodeContinueIf(CConnman::AllNodes, [&fFoundLocal, &empty](CNode* pnode) {
empty = false;
if (pnode->addr.IsIPv4())
fFoundLocal = GetLocal(activeMasternodeInfo.service, &pnode->addr) && CMasternode::IsValidNetAddr(activeMasternodeInfo.service);
return !fFoundLocal;
});
// nothing and no live connections, can't do anything for now
if (empty) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Can't detect valid external address. Will retry when there are some connections available.";
LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
}
if (!fFoundLocal && Params().NetworkIDString() == CBaseChainParams::REGTEST) {
if (Lookup("127.0.0.1", activeMasternodeInfo.service, GetListenPort(), false)) {
fFoundLocal = true;
}
}
if(!fFoundLocal) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
if(activeMasternodeInfo.service.GetPort() != mainnetDefaultPort) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", activeMasternodeInfo.service.GetPort(), mainnetDefaultPort);
LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
} else if(activeMasternodeInfo.service.GetPort() == mainnetDefaultPort) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", activeMasternodeInfo.service.GetPort(), mainnetDefaultPort);
LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
if(Params().NetworkIDString() != CBaseChainParams::REGTEST) {
// Check socket connectivity
LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- Checking inbound connection to '%s'\n", activeMasternodeInfo.service.ToString());
SOCKET hSocket;
bool fConnected = ConnectSocket(activeMasternodeInfo.service, hSocket, nConnectTimeout) && IsSelectableSocket(hSocket);
CloseSocket(hSocket);
if (!fConnected) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Could not connect to " + activeMasternodeInfo.service.ToString();
LogPrintf("CActiveLegacyMasternodeManager::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
}
// Default to REMOTE
eType = MASTERNODE_REMOTE;
LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
}
void CActiveLegacyMasternodeManager::ManageStateRemote()
{
if (deterministicMNManager->IsDeterministicMNsSporkActive())
return;
LogPrint("masternode", "CActiveLegacyMasternodeManager::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, keyIDOperator = %s\n",
GetStatus(), GetTypeString(), fPingerEnabled, activeMasternodeInfo.keyIDOperator.ToString());
mnodeman.CheckMasternode(activeMasternodeInfo.keyIDOperator, true);
masternode_info_t infoMn;
if(mnodeman.GetMasternodeInfo(activeMasternodeInfo.keyIDOperator, infoMn)) {
if(infoMn.nProtocolVersion != PROTOCOL_VERSION) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Invalid protocol version";
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
if(activeMasternodeInfo.service != infoMn.addr) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Broadcasted IP doesn't match our external address. Make sure you issued a new broadcast if IP of this masternode changed recently.";
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
if(!CMasternode::IsValidStateForAutoStart(infoMn.nActiveState)) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = strprintf("Masternode in %s state", CMasternode::StateToString(infoMn.nActiveState));
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(infoMn.outpoint.hash);
if (dmn) {
if (dmn->pdmnState->keyIDOperator != infoMn.keyIDOperator) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = strprintf("Masternode collateral is a ProTx and masternode key does not match key from -masternodeprivkey");
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
if (dmn->pdmnState->addr != infoMn.addr) {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = strprintf("Masternode collateral is a ProTx and ProTx address does not match local address");
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
return;
}
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- Collateral is a ProTx\n");
}
if(nState != ACTIVE_MASTERNODE_STARTED) {
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- STARTED!\n");
activeMasternodeInfo.outpoint = infoMn.outpoint;
activeMasternodeInfo.service = infoMn.addr;
fPingerEnabled = true;
nState = ACTIVE_MASTERNODE_STARTED;
}
}
else {
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
strNotCapableReason = "Masternode not in masternode list";
LogPrintf("CActiveLegacyMasternodeManager::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
}
}