00c84ca53e
6182d10 Do not increment nAttempts by more than one for every Good connection. (Gregory Maxwell) c769c4a Avoid counting failed connect attempts when probably offline. (Gregory Maxwell)
238 lines
10 KiB
C++
238 lines
10 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 "protocol.h"
|
|
|
|
// Keep track of the active Masternode
|
|
CActiveMasternode activeMasternode;
|
|
|
|
void CActiveMasternode::ManageState(CConnman& connman)
|
|
{
|
|
LogPrint("masternode", "CActiveMasternode::ManageState -- Start\n");
|
|
if(!fMasterNode) {
|
|
LogPrint("masternode", "CActiveMasternode::ManageState -- Not a masternode, returning\n");
|
|
return;
|
|
}
|
|
|
|
if(Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
|
|
nState = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
|
|
LogPrintf("CActiveMasternode::ManageState -- %s: %s\n", GetStateString(), GetStatus());
|
|
return;
|
|
}
|
|
|
|
if(nState == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) {
|
|
nState = ACTIVE_MASTERNODE_INITIAL;
|
|
}
|
|
|
|
LogPrint("masternode", "CActiveMasternode::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 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";
|
|
}
|
|
}
|
|
|
|
std::string CActiveMasternode::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 CActiveMasternode::GetTypeString() const
|
|
{
|
|
std::string strType;
|
|
switch(eType) {
|
|
case MASTERNODE_REMOTE:
|
|
strType = "REMOTE";
|
|
break;
|
|
default:
|
|
strType = "UNKNOWN";
|
|
break;
|
|
}
|
|
return strType;
|
|
}
|
|
|
|
bool CActiveMasternode::SendMasternodePing(CConnman& connman)
|
|
{
|
|
if(!fPingerEnabled) {
|
|
LogPrint("masternode", "CActiveMasternode::SendMasternodePing -- %s: masternode ping service is disabled, skipping...\n", GetStateString());
|
|
return false;
|
|
}
|
|
|
|
if(!mnodeman.Has(outpoint)) {
|
|
strNotCapableReason = "Masternode not in masternode list";
|
|
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
|
LogPrintf("CActiveMasternode::SendMasternodePing -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return false;
|
|
}
|
|
|
|
CMasternodePing mnp(outpoint);
|
|
mnp.nSentinelVersion = nSentinelVersion;
|
|
mnp.fSentinelIsCurrent =
|
|
(abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_WATCHDOG_MAX_SECONDS);
|
|
if(!mnp.Sign(keyMasternode, pubKeyMasternode)) {
|
|
LogPrintf("CActiveMasternode::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
|
|
return false;
|
|
}
|
|
|
|
// Update lastPing for our masternode in Masternode list
|
|
if(mnodeman.IsMasternodePingedWithin(outpoint, MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
|
|
LogPrintf("CActiveMasternode::SendMasternodePing -- Too early to send Masternode Ping\n");
|
|
return false;
|
|
}
|
|
|
|
mnodeman.SetMasternodeLastPing(outpoint, mnp);
|
|
|
|
LogPrintf("CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s\n", outpoint.ToStringShort());
|
|
mnp.Relay(connman);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CActiveMasternode::UpdateSentinelPing(int version)
|
|
{
|
|
nSentinelVersion = version;
|
|
nSentinelPingTime = GetAdjustedTime();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CActiveMasternode::ManageStateInitial(CConnman& connman)
|
|
{
|
|
LogPrint("masternode", "CActiveMasternode::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("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
|
|
// First try to find whatever local address is specified by externalip option
|
|
bool fFoundLocal = GetLocal(service) && CMasternode::IsValidNetAddr(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, this](CNode* pnode) {
|
|
empty = false;
|
|
if (pnode->addr.IsIPv4())
|
|
fFoundLocal = GetLocal(service, &pnode->addr) && CMasternode::IsValidNetAddr(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("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
}
|
|
|
|
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("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
|
|
int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
|
|
if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
|
|
if(service.GetPort() != mainnetDefaultPort) {
|
|
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
|
strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", service.GetPort(), mainnetDefaultPort);
|
|
LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
} else if(service.GetPort() == mainnetDefaultPort) {
|
|
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
|
strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", service.GetPort(), mainnetDefaultPort);
|
|
LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
|
|
LogPrintf("CActiveMasternode::ManageStateInitial -- Checking inbound connection to '%s'\n", service.ToString());
|
|
|
|
if(!connman.ConnectNode(CAddress(service, NODE_NETWORK), NULL, false, true)) {
|
|
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
|
strNotCapableReason = "Could not connect to " + service.ToString();
|
|
LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
|
|
// Default to REMOTE
|
|
eType = MASTERNODE_REMOTE;
|
|
|
|
LogPrint("masternode", "CActiveMasternode::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
|
|
}
|
|
|
|
void CActiveMasternode::ManageStateRemote()
|
|
{
|
|
LogPrint("masternode", "CActiveMasternode::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, pubKeyMasternode.GetID() = %s\n",
|
|
GetStatus(), GetTypeString(), fPingerEnabled, pubKeyMasternode.GetID().ToString());
|
|
|
|
mnodeman.CheckMasternode(pubKeyMasternode, true);
|
|
masternode_info_t infoMn;
|
|
if(mnodeman.GetMasternodeInfo(pubKeyMasternode, infoMn)) {
|
|
if(infoMn.nProtocolVersion != PROTOCOL_VERSION) {
|
|
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
|
strNotCapableReason = "Invalid protocol version";
|
|
LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
if(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("CActiveMasternode::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("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
return;
|
|
}
|
|
if(nState != ACTIVE_MASTERNODE_STARTED) {
|
|
LogPrintf("CActiveMasternode::ManageStateRemote -- STARTED!\n");
|
|
outpoint = infoMn.vin.prevout;
|
|
service = infoMn.addr;
|
|
fPingerEnabled = true;
|
|
nState = ACTIVE_MASTERNODE_STARTED;
|
|
}
|
|
}
|
|
else {
|
|
nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
|
|
strNotCapableReason = "Masternode not in masternode list";
|
|
LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
|
|
}
|
|
}
|