diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 662032558..a84a970d5 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -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"); @@ -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; @@ -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 @@ -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()); diff --git a/src/activemasternode.h b/src/activemasternode.h index f6a17150d..c937d57e0 100644 --- a/src/activemasternode.h +++ b/src/activemasternode.h @@ -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; @@ -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 @@ -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: diff --git a/src/init.cpp b/src/init.cpp index 8fbf91781..e148b6e72 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -318,6 +318,9 @@ void PrepareShutdown() delete pdsNotificationInterface; pdsNotificationInterface = NULL; } + if (fMasternodeMode) { + UnregisterValidationInterface(activeMasternodeManager); + } #ifndef WIN32 try { @@ -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 @@ -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) {