Skip to content

Commit

Permalink
Implement CActiveDeterministicMasternodeManager
Browse files Browse the repository at this point in the history
  • Loading branch information
codablock committed Sep 3, 2018
1 parent a5e65aa commit d90b139
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 1 deletion.
140 changes: 140 additions & 0 deletions src/activemasternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,144 @@
#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");
Expand Down Expand Up @@ -84,6 +215,9 @@ std::string CActiveLegacyMasternodeManager::GetTypeString() const

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;
Expand Down Expand Up @@ -129,6 +263,9 @@ bool CActiveLegacyMasternodeManager::UpdateSentinelPing(int version)

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
Expand Down Expand Up @@ -210,6 +347,9 @@ void CActiveLegacyMasternodeManager::ManageStateInitial(CConnman& connman)

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());

Expand Down
40 changes: 39 additions & 1 deletion src/activemasternode.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
#include "key.h"
#include "net.h"
#include "primitives/transaction.h"
#include "validationinterface.h"

#include "evo/providertx.h"
#include "evo/deterministicmns.h"

struct CActiveMasternodeInfo;
class CActiveLegacyMasternodeManager;
class CActiveDeterministicMasternodeManager;

static const int ACTIVE_MASTERNODE_INITIAL = 0; // initial state
static const int ACTIVE_MASTERNODE_SYNC_IN_PROCESS = 1;
Expand All @@ -21,6 +26,7 @@ static const int ACTIVE_MASTERNODE_STARTED = 4;

extern CActiveMasternodeInfo activeMasternodeInfo;
extern CActiveLegacyMasternodeManager legacyActiveMasternodeManager;
extern CActiveDeterministicMasternodeManager* activeMasternodeManager;

struct CActiveMasternodeInfo {
// Keys for the active Masternode
Expand All @@ -32,7 +38,39 @@ struct CActiveMasternodeInfo {
CService service;
};

// Responsible for activating the Masternode and pinging the network

class CActiveDeterministicMasternodeManager : public CValidationInterface
{
public:
enum masternode_state_t {
MASTERNODE_WAITING_FOR_PROTX,
MASTERNODE_POSE_BANNED,
MASTERNODE_REMOVED,
MASTERNODE_READY,
MASTERNODE_ERROR,
};

private:
CDeterministicMNCPtr mnListEntry;
masternode_state_t state{MASTERNODE_WAITING_FOR_PROTX};
std::string strError;

public:
virtual void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload);

void Init();

CDeterministicMNCPtr GetDMN() const { return mnListEntry; }

masternode_state_t GetState() const { return state; }
std::string GetStateString() const;
std::string GetStatus() const;

private:
bool GetLocalAddress(CService &addrRet);
};

// Responsible for activating the Masternode and pinging the network (legacy MN list)
class CActiveLegacyMasternodeManager
{
public:
Expand Down
10 changes: 10 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ void PrepareShutdown()
delete pdsNotificationInterface;
pdsNotificationInterface = NULL;
}
if (fMasternodeMode) {
UnregisterValidationInterface(activeMasternodeManager);
}

#ifndef WIN32
try {
Expand Down Expand Up @@ -1880,6 +1883,10 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
} else {
return InitError(_("You must specify a masternodeprivkey in the configuration. Please see documentation for help."));
}

// init and register activeMasternodeManager
activeMasternodeManager = new CActiveDeterministicMasternodeManager();
RegisterValidationInterface(activeMasternodeManager);
}

#ifdef ENABLE_WALLET
Expand Down Expand Up @@ -1996,6 +2003,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
// GetMainSignals().UpdatedBlockTip(chainActive.Tip());
pdsNotificationInterface->InitializeCurrentBlockTip();

if (activeMasternodeManager && fDIP0003ActiveAtTip)
activeMasternodeManager->Init();

// ********************************************************* Step 11d: schedule Dash-specific tasks

if (!fLiteMode) {
Expand Down

0 comments on commit d90b139

Please sign in to comment.