Merge pull request #2255 from codablock/pr_dip3_logic
DIP3 compatibility code
This commit is contained in:
commit
794921b7b5
@ -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());
|
||||
|
||||
@ -234,6 +374,22 @@ void CActiveLegacyMasternodeManager::ManageStateRemote()
|
||||
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;
|
||||
|
@ -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:
|
||||
|
10
src/init.cpp
10
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) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "spork.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#include "evo/deterministicmns.h"
|
||||
|
||||
class CMasternodeSync;
|
||||
CMasternodeSync masternodeSync;
|
||||
@ -69,12 +70,20 @@ void CMasternodeSync::SwitchToNextAsset(CConnman& connman)
|
||||
break;
|
||||
case(MASTERNODE_SYNC_WAITING):
|
||||
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
nRequestedMasternodeAssets = MASTERNODE_SYNC_GOVERNANCE;
|
||||
} else {
|
||||
nRequestedMasternodeAssets = MASTERNODE_SYNC_LIST;
|
||||
}
|
||||
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
|
||||
break;
|
||||
case(MASTERNODE_SYNC_LIST):
|
||||
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Completed %s in %llds\n", GetAssetName(), GetTime() - nTimeAssetSyncStarted);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
nRequestedMasternodeAssets = MASTERNODE_SYNC_GOVERNANCE;
|
||||
} else {
|
||||
nRequestedMasternodeAssets = MASTERNODE_SYNC_MNW;
|
||||
}
|
||||
LogPrintf("CMasternodeSync::SwitchToNextAsset -- Starting %s\n", GetAssetName());
|
||||
break;
|
||||
case(MASTERNODE_SYNC_MNW):
|
||||
@ -188,15 +197,19 @@ void CMasternodeSync::ProcessTick(CConnman& connman)
|
||||
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETSPORKS)); //get current network sporks
|
||||
SwitchToNextAsset(connman);
|
||||
} else if (nRequestedMasternodeAssets == MASTERNODE_SYNC_LIST) {
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
mnodeman.DsegUpdate(pnode, connman);
|
||||
}
|
||||
SwitchToNextAsset(connman);
|
||||
} else if (nRequestedMasternodeAssets == MASTERNODE_SYNC_MNW) {
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
//sync payment votes
|
||||
if(pnode->nVersion == 70208) {
|
||||
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MASTERNODEPAYMENTSYNC, mnpayments.GetStorageLimit())); //sync payment votes
|
||||
} else {
|
||||
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::MASTERNODEPAYMENTSYNC)); //sync payment votes
|
||||
}
|
||||
}
|
||||
SwitchToNextAsset(connman);
|
||||
} else if (nRequestedMasternodeAssets == MASTERNODE_SYNC_GOVERNANCE) {
|
||||
SendGovernanceSyncRequest(pnode, connman);
|
||||
@ -245,6 +258,12 @@ void CMasternodeSync::ProcessTick(CConnman& connman)
|
||||
// MNLIST : SYNC MASTERNODE LIST FROM OTHER CONNECTED CLIENTS
|
||||
|
||||
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_LIST) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
SwitchToNextAsset(connman);
|
||||
connman.ReleaseNodeVector(vNodesCopy);
|
||||
return;
|
||||
}
|
||||
|
||||
LogPrint("masternode", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped);
|
||||
// check for timeout first
|
||||
if(GetTime() - nTimeLastBumped > MASTERNODE_SYNC_TIMEOUT_SECONDS) {
|
||||
@ -283,6 +302,12 @@ void CMasternodeSync::ProcessTick(CConnman& connman)
|
||||
// MNW : SYNC MASTERNODE PAYMENT VOTES FROM OTHER CONNECTED CLIENTS
|
||||
|
||||
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_MNW) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
SwitchToNextAsset(connman);
|
||||
connman.ReleaseNodeVector(vNodesCopy);
|
||||
return;
|
||||
}
|
||||
|
||||
LogPrint("mnpayments", "CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nRequestedMasternodeAssets, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped);
|
||||
// check for timeout first
|
||||
// This might take a lot longer than MASTERNODE_SYNC_TIMEOUT_SECONDS due to new blocks,
|
||||
|
@ -52,6 +52,17 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
|
||||
fAllowMixingTx(true)
|
||||
{}
|
||||
|
||||
CMasternode::CMasternode(const uint256 &proTxHash, const CDeterministicMNCPtr& dmn) :
|
||||
masternode_info_t{ MASTERNODE_ENABLED, dmn->pdmnState->nProtocolVersion, GetAdjustedTime(),
|
||||
COutPoint(proTxHash, dmn->nCollateralIndex), dmn->pdmnState->addr, CKeyID(), dmn->pdmnState->keyIDOwner, dmn->pdmnState->keyIDOperator, dmn->pdmnState->keyIDVoting},
|
||||
fAllowMixingTx(true)
|
||||
{
|
||||
CTxDestination dest;
|
||||
if (!ExtractDestination(dmn->pdmnState->scriptPayout, dest) || !boost::get<CKeyID>(&dest))
|
||||
assert(false); // should not happen (previous verification forbids non p2pkh/p2pk
|
||||
keyIDCollateralAddress = *boost::get<CKeyID>(&dest);
|
||||
}
|
||||
|
||||
//
|
||||
// When a new masternode broadcast is sent, update our information
|
||||
//
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "validation.h"
|
||||
#include "spork.h"
|
||||
|
||||
#include "evo/deterministicmns.h"
|
||||
|
||||
class CMasternode;
|
||||
class CMasternodeBroadcast;
|
||||
class CConnman;
|
||||
@ -214,6 +216,7 @@ public:
|
||||
CMasternode(const CMasternode& other);
|
||||
CMasternode(const CMasternodeBroadcast& mnb);
|
||||
CMasternode(CService addrNew, COutPoint outpointNew, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int nProtocolVersionIn);
|
||||
CMasternode(const uint256 &proTxHash, const CDeterministicMNCPtr& dmn);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include "util.h"
|
||||
#include "warnings.h"
|
||||
|
||||
#include "evo/deterministicmns.h"
|
||||
#include "evo/providertx.h"
|
||||
|
||||
/** Masternode manager */
|
||||
CMasternodeMan mnodeman;
|
||||
|
||||
@ -79,6 +82,9 @@ bool CMasternodeMan::Add(CMasternode &mn)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return false;
|
||||
|
||||
if (Has(mn.outpoint)) return false;
|
||||
|
||||
LogPrint("masternode", "CMasternodeMan::Add -- Adding new Masternode: addr=%s, %i now\n", mn.addr.ToString(), size() + 1);
|
||||
@ -94,6 +100,9 @@ void CMasternodeMan::AskForMN(CNode* pnode, const COutPoint& outpoint, CConnman&
|
||||
CNetMsgMaker msgMaker(pnode->GetSendVersion());
|
||||
LOCK(cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
|
||||
auto it1 = mWeAskedForMasternodeListEntry.find(outpoint);
|
||||
if (it1 != mWeAskedForMasternodeListEntry.end()) {
|
||||
@ -151,6 +160,10 @@ bool CMasternodeMan::DisallowMixing(const COutPoint &outpoint)
|
||||
bool CMasternodeMan::PoSeBan(const COutPoint &outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return true;
|
||||
|
||||
CMasternode* pmn = Find(outpoint);
|
||||
if (!pmn) {
|
||||
return false;
|
||||
@ -164,6 +177,9 @@ void CMasternodeMan::Check()
|
||||
{
|
||||
LOCK2(cs_main, cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
for (auto& mnpair : mapMasternodes) {
|
||||
// NOTE: internally it checks only every MASTERNODE_CHECK_SECONDS seconds
|
||||
// since the last time, so expect some MNs to skip this
|
||||
@ -173,6 +189,9 @@ void CMasternodeMan::Check()
|
||||
|
||||
void CMasternodeMan::CheckAndRemove(CConnman& connman)
|
||||
{
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
if(!masternodeSync.IsMasternodeListSynced()) return;
|
||||
|
||||
LogPrintf("CMasternodeMan::CheckAndRemove\n");
|
||||
@ -355,6 +374,69 @@ void CMasternodeMan::CheckAndRemove(CConnman& connman)
|
||||
}
|
||||
}
|
||||
|
||||
void CMasternodeMan::AddDeterministicMasternodes()
|
||||
{
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
bool added = false;
|
||||
{
|
||||
LOCK(cs);
|
||||
unsigned int oldMnCount = mapMasternodes.size();
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
for (const auto& dmn : mnList.valid_range()) {
|
||||
// call Find() on each deterministic MN to force creation of CMasternode object
|
||||
auto mn = Find(COutPoint(dmn->proTxHash, dmn->nCollateralIndex));
|
||||
assert(mn);
|
||||
|
||||
// make sure we use the splitted keys from now on
|
||||
mn->keyIDOwner = dmn->pdmnState->keyIDOwner;
|
||||
mn->keyIDOperator = dmn->pdmnState->keyIDOperator;
|
||||
mn->keyIDVoting = dmn->pdmnState->keyIDVoting;
|
||||
mn->addr = dmn->pdmnState->addr;
|
||||
mn->nProtocolVersion = dmn->pdmnState->nProtocolVersion;
|
||||
|
||||
// If it appeared in the valid list, it is enabled no matter what
|
||||
mn->nActiveState = CMasternode::MASTERNODE_ENABLED;
|
||||
}
|
||||
|
||||
added = oldMnCount != mapMasternodes.size();
|
||||
}
|
||||
|
||||
if (added) {
|
||||
NotifyMasternodeUpdates(*g_connman, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
void CMasternodeMan::RemoveNonDeterministicMasternodes()
|
||||
{
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
bool erased = false;
|
||||
{
|
||||
LOCK(cs);
|
||||
std::set<COutPoint> mnSet;
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
for (const auto& dmn : mnList.valid_range()) {
|
||||
mnSet.insert(COutPoint(dmn->proTxHash, dmn->nCollateralIndex));
|
||||
}
|
||||
auto it = mapMasternodes.begin();
|
||||
while (it != mapMasternodes.end()) {
|
||||
if (!mnSet.count(it->second.outpoint)) {
|
||||
mapMasternodes.erase(it++);
|
||||
erased = true;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (erased) {
|
||||
NotifyMasternodeUpdates(*g_connman, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CMasternodeMan::Clear()
|
||||
{
|
||||
LOCK(cs);
|
||||
@ -371,20 +453,32 @@ void CMasternodeMan::Clear()
|
||||
int CMasternodeMan::CountMasternodes(int nProtocolVersion)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
int nCount = 0;
|
||||
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
for (const auto& dmn : mnList.valid_range()) {
|
||||
if (dmn->pdmnState->nProtocolVersion < nProtocolVersion) continue;
|
||||
nCount++;
|
||||
}
|
||||
} else {
|
||||
for (const auto& mnpair : mapMasternodes) {
|
||||
if(mnpair.second.nProtocolVersion < nProtocolVersion) continue;
|
||||
nCount++;
|
||||
}
|
||||
|
||||
}
|
||||
return nCount;
|
||||
}
|
||||
|
||||
int CMasternodeMan::CountEnabled(int nProtocolVersion)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return CountMasternodes(nProtocolVersion);
|
||||
|
||||
int nCount = 0;
|
||||
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
|
||||
|
||||
@ -418,6 +512,9 @@ void CMasternodeMan::DsegUpdate(CNode* pnode, CConnman& connman)
|
||||
CNetMsgMaker msgMaker(pnode->GetSendVersion());
|
||||
LOCK(cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
CService addrSquashed = Params().AllowMultiplePorts() ? (CService)pnode->addr : CService(pnode->addr, 0);
|
||||
if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
|
||||
if(!(pnode->addr.IsRFC1918() || pnode->addr.IsLocal())) {
|
||||
@ -443,36 +540,69 @@ void CMasternodeMan::DsegUpdate(CNode* pnode, CConnman& connman)
|
||||
CMasternode* CMasternodeMan::Find(const COutPoint &outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
// This code keeps compatibility to old code depending on the non-deterministic MN lists
|
||||
// When deterministic MN lists get activated, we stop relying on the MNs we encountered due to MNBs and start
|
||||
// using the MNs found in the deterministic MN manager. To keep compatibility, we create CMasternode entries
|
||||
// for these and return them here. This is needed because we also need to track some data per MN that is not
|
||||
// on-chain, like vote counts
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
if (!mnList.IsMNValid(outpoint.hash)) {
|
||||
return nullptr;
|
||||
}
|
||||
auto dmn = mnList.GetMN(outpoint.hash);
|
||||
if (!dmn) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto it = mapMasternodes.find(outpoint);
|
||||
if (it != mapMasternodes.end()) {
|
||||
return &(it->second);
|
||||
} else {
|
||||
// MN is not in mapMasternodes but in the deterministic list. Create an entry in mapMasternodes for compatibility with legacy code
|
||||
CMasternode mn(outpoint.hash, dmn);
|
||||
it = mapMasternodes.emplace(outpoint, mn).first;
|
||||
return &(it->second);
|
||||
}
|
||||
} else {
|
||||
auto it = mapMasternodes.find(outpoint);
|
||||
return it == mapMasternodes.end() ? nullptr : &(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool CMasternodeMan::Get(const COutPoint& outpoint, CMasternode& masternodeRet)
|
||||
{
|
||||
// Theses mutexes are recursive so double locking by the same thread is safe.
|
||||
LOCK(cs);
|
||||
auto it = mapMasternodes.find(outpoint);
|
||||
if (it == mapMasternodes.end()) {
|
||||
CMasternode* mn = Find(outpoint);
|
||||
if (!mn)
|
||||
return false;
|
||||
}
|
||||
|
||||
masternodeRet = it->second;
|
||||
masternodeRet = *mn;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMasternodeMan::GetMasternodeInfo(const COutPoint& outpoint, masternode_info_t& mnInfoRet)
|
||||
{
|
||||
LOCK(cs);
|
||||
auto it = mapMasternodes.find(outpoint);
|
||||
if (it == mapMasternodes.end()) {
|
||||
CMasternode* mn = Find(outpoint);
|
||||
if (!mn)
|
||||
return false;
|
||||
}
|
||||
mnInfoRet = it->second.GetInfo();
|
||||
mnInfoRet = mn->GetInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMasternodeMan::GetMasternodeInfo(const CKeyID& keyIDOperator, masternode_info_t& mnInfoRet) {
|
||||
LOCK(cs);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetMNByOperatorKey(keyIDOperator);
|
||||
if (dmn) {
|
||||
return GetMasternodeInfo(COutPoint(dmn->proTxHash, dmn->nCollateralIndex), mnInfoRet);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
for (const auto& mnpair : mapMasternodes) {
|
||||
if (mnpair.second.keyIDOperator == keyIDOperator) {
|
||||
mnInfoRet = mnpair.second.GetInfo();
|
||||
@ -481,6 +611,7 @@ bool CMasternodeMan::GetMasternodeInfo(const CKeyID& keyIDOperator, masternode_i
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMasternodeMan::GetMasternodeInfo(const CPubKey& pubKeyOperator, masternode_info_t& mnInfoRet)
|
||||
{
|
||||
@ -506,8 +637,12 @@ bool CMasternodeMan::GetMasternodeInfo(const CScript& payee, masternode_info_t&
|
||||
bool CMasternodeMan::Has(const COutPoint& outpoint)
|
||||
{
|
||||
LOCK(cs);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
return deterministicMNManager->HasValidMNAtChainTip(outpoint.hash);
|
||||
} else {
|
||||
return mapMasternodes.find(outpoint) != mapMasternodes.end();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Deterministically select the oldest/best masternode to pay on the network
|
||||
@ -627,6 +762,8 @@ masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<COutPoint
|
||||
}
|
||||
}
|
||||
if(fExclude) continue;
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive() && !deterministicMNManager->HasValidMNAtChainTip(pmn->outpoint.hash))
|
||||
continue;
|
||||
// found the one not in vecToExclude
|
||||
LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- found, masternode=%s\n", pmn->outpoint.ToStringShort());
|
||||
return pmn->GetInfo();
|
||||
@ -636,6 +773,23 @@ masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<COutPoint
|
||||
return masternode_info_t();
|
||||
}
|
||||
|
||||
std::map<COutPoint, CMasternode> CMasternodeMan::GetFullMasternodeMap()
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
std::map<COutPoint, CMasternode> result;
|
||||
for (const auto &p : mapMasternodes) {
|
||||
if (deterministicMNManager->HasValidMNAtChainTip(p.first.hash)) {
|
||||
result.emplace(p.first, p.second);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return mapMasternodes;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol)
|
||||
{
|
||||
vecMasternodeScoresRet.clear();
|
||||
@ -650,6 +804,9 @@ bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeM
|
||||
|
||||
// calculate scores
|
||||
for (const auto& mnpair : mapMasternodes) {
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive() && !deterministicMNManager->HasValidMNAtChainTip(mnpair.second.outpoint.hash))
|
||||
continue;
|
||||
|
||||
if (mnpair.second.nProtocolVersion >= nMinProtocol) {
|
||||
vecMasternodeScoresRet.push_back(std::make_pair(mnpair.second.CalculateScore(nBlockHash), &mnpair.second));
|
||||
}
|
||||
@ -740,6 +897,9 @@ void CMasternodeMan::ProcessMasternodeConnections(CConnman& connman)
|
||||
std::pair<CService, std::set<uint256> > CMasternodeMan::PopScheduledMnbRequestConnection()
|
||||
{
|
||||
LOCK(cs);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
return std::make_pair(CService(), std::set<uint256>());
|
||||
}
|
||||
if(listScheduledMnbRequestConnections.empty()) {
|
||||
return std::make_pair(CService(), std::set<uint256>());
|
||||
}
|
||||
@ -766,6 +926,9 @@ std::pair<CService, std::set<uint256> > CMasternodeMan::PopScheduledMnbRequestCo
|
||||
|
||||
void CMasternodeMan::ProcessPendingMnbRequests(CConnman& connman)
|
||||
{
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
std::pair<CService, std::set<uint256> > p = PopScheduledMnbRequestConnection();
|
||||
if (!(p.first == CService() || p.second.empty())) {
|
||||
if (connman.IsMasternodeOrDisconnectRequested(p.first)) return;
|
||||
@ -805,6 +968,9 @@ void CMasternodeMan::ProcessPendingMnbRequests(CConnman& connman)
|
||||
|
||||
void CMasternodeMan::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
|
||||
{
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
if(fLiteMode) return; // disable all Dash specific functionality
|
||||
|
||||
if (strCommand == NetMsgType::MNANNOUNCE) { //Masternode Broadcast
|
||||
@ -1001,6 +1167,9 @@ void CMasternodeMan::PushDsegInvs(CNode* pnode, const CMasternode& mn)
|
||||
|
||||
void CMasternodeMan::DoFullVerificationStep(CConnman& connman)
|
||||
{
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
if(activeMasternodeInfo.outpoint.IsNull()) return;
|
||||
if(!masternodeSync.IsSynced()) return;
|
||||
|
||||
@ -1078,6 +1247,9 @@ void CMasternodeMan::DoFullVerificationStep(CConnman& connman)
|
||||
|
||||
void CMasternodeMan::CheckSameAddr()
|
||||
{
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
if(!masternodeSync.IsSynced() || mapMasternodes.empty()) return;
|
||||
|
||||
std::vector<CMasternode*> vBan;
|
||||
@ -1131,6 +1303,9 @@ void CMasternodeMan::CheckSameAddr()
|
||||
|
||||
bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vector<const CMasternode*>& vSortedByAddr, CConnman& connman)
|
||||
{
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return false;
|
||||
|
||||
if(netfulfilledman.HasFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request")) {
|
||||
// we already asked for verification, not a good idea to do this too often, skip it
|
||||
LogPrint("masternode", "CMasternodeMan::SendVerifyRequest -- too many requests, skipping... addr=%s\n", addr.ToString());
|
||||
@ -1152,6 +1327,9 @@ void CMasternodeMan::ProcessPendingMnvRequests(CConnman& connman)
|
||||
{
|
||||
LOCK(cs_mapPendingMNV);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
std::map<CService, std::pair<int64_t, CMasternodeVerification> >::iterator itPendingMNV = mapPendingMNV.begin();
|
||||
|
||||
while (itPendingMNV != mapPendingMNV.end()) {
|
||||
@ -1181,6 +1359,9 @@ void CMasternodeMan::SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv,
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
// only masternodes can sign this, why would someone ask regular node?
|
||||
if(!fMasternodeMode) {
|
||||
// do not ban, malicious node might be using my IP
|
||||
@ -1238,6 +1419,9 @@ void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& m
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
std::string strError;
|
||||
|
||||
// did we even ask for it? if that's the case we should have matching fulfilled request
|
||||
@ -1374,6 +1558,9 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
|
||||
std::string strError;
|
||||
|
||||
if(mapSeenMasternodeVerification.find(mnv.GetHash()) != mapSeenMasternodeVerification.end()) {
|
||||
@ -1495,12 +1682,17 @@ std::string CMasternodeMan::ToString() const
|
||||
{
|
||||
std::ostringstream info;
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
info << "Masternodes: masternode object count: " << (int)mapMasternodes.size() <<
|
||||
", deterministic masternode count: " << deterministicMNManager->GetListAtChainTip().size() <<
|
||||
", nDsqCount: " << (int)nDsqCount;
|
||||
} else {
|
||||
info << "Masternodes: " << (int)mapMasternodes.size() <<
|
||||
", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size() <<
|
||||
", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size() <<
|
||||
", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size() <<
|
||||
", nDsqCount: " << (int)nDsqCount;
|
||||
|
||||
}
|
||||
return info.str();
|
||||
}
|
||||
|
||||
@ -1509,6 +1701,9 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBr
|
||||
// Need to lock cs_main here to ensure consistent locking order because the SimpleCheck call below locks cs_main
|
||||
LOCK(cs_main);
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return false;
|
||||
|
||||
{
|
||||
LOCK(cs);
|
||||
nDos = 0;
|
||||
@ -1621,6 +1816,8 @@ void CMasternodeMan::UpdateLastPaid(const CBlockIndex* pindex)
|
||||
void CMasternodeMan::UpdateLastSentinelPingTime()
|
||||
{
|
||||
LOCK(cs);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
nLastSentinelPingTime = GetTime();
|
||||
}
|
||||
|
||||
@ -1653,6 +1850,8 @@ void CMasternodeMan::RemoveGovernanceObject(uint256 nGovernanceObjectHash)
|
||||
void CMasternodeMan::CheckMasternode(const CKeyID& keyIDOperator, bool fForce)
|
||||
{
|
||||
LOCK2(cs_main, cs);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
for (auto& mnpair : mapMasternodes) {
|
||||
if (mnpair.second.keyIDOperator == keyIDOperator) {
|
||||
mnpair.second.Check(fForce);
|
||||
@ -1671,6 +1870,8 @@ bool CMasternodeMan::IsMasternodePingedWithin(const COutPoint& outpoint, int nSe
|
||||
void CMasternodeMan::SetMasternodeLastPing(const COutPoint& outpoint, const CMasternodePing& mnp)
|
||||
{
|
||||
LOCK(cs);
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
return;
|
||||
CMasternode* pmn = Find(outpoint);
|
||||
if(!pmn) {
|
||||
return;
|
||||
@ -1693,6 +1894,9 @@ void CMasternodeMan::UpdatedBlockTip(const CBlockIndex *pindex)
|
||||
nCachedBlockHeight = pindex->nHeight;
|
||||
LogPrint("masternode", "CMasternodeMan::UpdatedBlockTip -- nCachedBlockHeight=%d\n", nCachedBlockHeight);
|
||||
|
||||
AddDeterministicMasternodes();
|
||||
RemoveNonDeterministicMasternodes();
|
||||
|
||||
CheckSameAddr();
|
||||
|
||||
if(fMasternodeMode) {
|
||||
@ -1742,7 +1946,7 @@ void CMasternodeMan::WarnMasternodeDaemonUpdates()
|
||||
fWarned = true;
|
||||
}
|
||||
|
||||
void CMasternodeMan::NotifyMasternodeUpdates(CConnman& connman)
|
||||
void CMasternodeMan::NotifyMasternodeUpdates(CConnman& connman, bool forceAddedChecks, bool forceRemovedChecks)
|
||||
{
|
||||
// Avoid double locking
|
||||
bool fMasternodesAddedLocal = false;
|
||||
@ -1753,11 +1957,11 @@ void CMasternodeMan::NotifyMasternodeUpdates(CConnman& connman)
|
||||
fMasternodesRemovedLocal = fMasternodesRemoved;
|
||||
}
|
||||
|
||||
if(fMasternodesAddedLocal) {
|
||||
if(fMasternodesAddedLocal || forceAddedChecks) {
|
||||
governance.CheckMasternodeOrphanObjects(connman);
|
||||
governance.CheckMasternodeOrphanVotes(connman);
|
||||
}
|
||||
if(fMasternodesRemovedLocal) {
|
||||
if(fMasternodesRemovedLocal || forceRemovedChecks) {
|
||||
governance.UpdateCachesAndClean();
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,9 @@ public:
|
||||
/// This is dummy overload to be used for dumping/loading mncache.dat
|
||||
void CheckAndRemove() {}
|
||||
|
||||
void AddDeterministicMasternodes();
|
||||
void RemoveNonDeterministicMasternodes();
|
||||
|
||||
/// Clear Masternode vector
|
||||
void Clear();
|
||||
|
||||
@ -181,7 +184,7 @@ public:
|
||||
/// Find a random entry
|
||||
masternode_info_t FindRandomNotInVec(const std::vector<COutPoint> &vecToExclude, int nProtocolVersion = -1);
|
||||
|
||||
std::map<COutPoint, CMasternode> GetFullMasternodeMap() { return mapMasternodes; }
|
||||
std::map<COutPoint, CMasternode> GetFullMasternodeMap();
|
||||
|
||||
bool GetMasternodeRanks(rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight = -1, int nMinProtocol = 0);
|
||||
bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, int nBlockHeight = -1, int nMinProtocol = 0);
|
||||
@ -243,7 +246,7 @@ public:
|
||||
* Called to notify CGovernanceManager that the masternode index has been updated.
|
||||
* Must be called while not holding the CMasternodeMan::cs mutex
|
||||
*/
|
||||
void NotifyMasternodeUpdates(CConnman& connman);
|
||||
void NotifyMasternodeUpdates(CConnman& connman, bool forceAddedChecks = false, bool forceRemovedChecks = false);
|
||||
|
||||
void DoMaintenance(CConnman &connman);
|
||||
};
|
||||
|
@ -1201,18 +1201,22 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
||||
}
|
||||
|
||||
if (!push && inv.type == MSG_MASTERNODE_ANNOUNCE) {
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
if (mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)) {
|
||||
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNANNOUNCE, mnodeman.mapSeenMasternodeBroadcast[inv.hash].second));
|
||||
push = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!push && inv.type == MSG_MASTERNODE_PING) {
|
||||
if (!deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
if (mnodeman.mapSeenMasternodePing.count(inv.hash)) {
|
||||
connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNPING, mnodeman.mapSeenMasternodePing[inv.hash]));
|
||||
push = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!push && inv.type == MSG_DSTX) {
|
||||
CDarksendBroadcastTx dstx = CPrivateSend::GetDSTX(inv.hash);
|
||||
|
@ -19,6 +19,10 @@
|
||||
#include "rpc/server.h"
|
||||
#include "util.h"
|
||||
#include "utilmoneystr.h"
|
||||
#include "txmempool.h"
|
||||
|
||||
#include "evo/specialtx.h"
|
||||
#include "evo/deterministicmns.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
@ -327,6 +331,8 @@ UniValue masternode_start_alias(const JSONRPCRequest& request)
|
||||
{
|
||||
if(request.fHelp || request.params.size() < 2)
|
||||
masternode_start_alias_help();
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "start-alias is not supported when deterministic masternode list is active (DIP3)");
|
||||
|
||||
if (!EnsureWalletIsAvailable(request.fHelp))
|
||||
return NullUniValue;
|
||||
@ -427,6 +433,8 @@ UniValue masternode_start_all(const JSONRPCRequest& request)
|
||||
{
|
||||
if(request.fHelp)
|
||||
masternode_start_all_help();
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive())
|
||||
throw JSONRPCError(RPC_MISC_ERROR, strprintf("start-all is not supported when deterministic masternode list is active (DIP3)"));
|
||||
|
||||
if (!EnsureWalletIsAvailable(request.fHelp))
|
||||
return NullUniValue;
|
||||
@ -569,6 +577,91 @@ UniValue masternode_genkey(const JSONRPCRequest& request)
|
||||
return CBitcoinSecret(secret).ToString();
|
||||
}
|
||||
|
||||
void masternode_info_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"masternode info \"proTxHash\"\n"
|
||||
"Print masternode information of specified masternode\n"
|
||||
"\nArguments:\n"
|
||||
"1. proTxHash (string, required) proTxHash of masternode\n"
|
||||
);
|
||||
}
|
||||
|
||||
UniValue masternode_info(const JSONRPCRequest& request)
|
||||
{
|
||||
if(request.fHelp || request.params.size() != 2)
|
||||
masternode_info_help();
|
||||
|
||||
std::string strProTxHash = request.params[1].get_str();
|
||||
if (!IsHex(strProTxHash) || strProTxHash.size() != 64)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid \"proTxHash\"");
|
||||
|
||||
uint256 proTxHash;
|
||||
proTxHash.SetHex(strProTxHash);
|
||||
|
||||
CTransactionRef tx;
|
||||
uint256 hashBlock;
|
||||
bool fromMempool = false;
|
||||
|
||||
auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(proTxHash);
|
||||
if (!dmn) {
|
||||
tx = mempool.get(proTxHash);
|
||||
if (tx) {
|
||||
fromMempool = true;
|
||||
if (tx->nVersion < 3 || tx->nType != TRANSACTION_PROVIDER_REGISTER)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX is not a ProTx");
|
||||
CProRegTx tmpProTx;
|
||||
if (!GetTxPayload(*tx, tmpProTx))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX is not a valid ProTx");
|
||||
dmn = std::make_shared<CDeterministicMN>(tx->GetHash(), tmpProTx);
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "ProTx not found");
|
||||
}
|
||||
} else {
|
||||
if (!GetTransaction(proTxHash, tx, Params().GetConsensus(), hashBlock, true))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Parent transaction of ProTx not found");
|
||||
|
||||
if (!mapBlockIndex.count(hashBlock))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Parent transaction of ProTx not found");
|
||||
}
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
|
||||
UniValue stateObj;
|
||||
dmn->pdmnState->ToJson(stateObj);
|
||||
obj.push_back(Pair("state", stateObj));
|
||||
|
||||
if (!hashBlock.IsNull()) {
|
||||
UniValue blockObj(UniValue::VOBJ);
|
||||
blockObj.push_back(Pair("blockhash", hashBlock.GetHex()));
|
||||
|
||||
LOCK(cs_main);
|
||||
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
|
||||
if (mi != mapBlockIndex.end() && (*mi).second) {
|
||||
CBlockIndex *pindex = (*mi).second;
|
||||
if (chainActive.Contains(pindex)) {
|
||||
blockObj.push_back(Pair("height", pindex->nHeight));
|
||||
blockObj.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
|
||||
blockObj.push_back(Pair("time", pindex->GetBlockTime()));
|
||||
blockObj.push_back(Pair("blocktime", pindex->GetBlockTime()));
|
||||
} else {
|
||||
blockObj.push_back(Pair("height", -1));
|
||||
blockObj.push_back(Pair("confirmations", 0));
|
||||
}
|
||||
}
|
||||
obj.push_back(Pair("block", blockObj));
|
||||
|
||||
if (GetUTXOHeight(COutPoint(proTxHash, dmn->nCollateralIndex)) < 0) {
|
||||
obj.push_back(Pair("isSpent", true));
|
||||
}
|
||||
|
||||
} else {
|
||||
obj.push_back(Pair("fromMempool", true));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void masternode_list_conf_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
@ -622,15 +715,29 @@ UniValue masternode_status(const JSONRPCRequest& request)
|
||||
|
||||
UniValue mnObj(UniValue::VOBJ);
|
||||
|
||||
// keep compatibility with legacy status for now (might get deprecated/removed later)
|
||||
mnObj.push_back(Pair("outpoint", activeMasternodeInfo.outpoint.ToStringShort()));
|
||||
mnObj.push_back(Pair("service", activeMasternodeInfo.service.ToString()));
|
||||
|
||||
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
|
||||
auto dmn = activeMasternodeManager->GetDMN();
|
||||
if (dmn) {
|
||||
mnObj.push_back(Pair("proTxHash", dmn->proTxHash.ToString()));
|
||||
mnObj.push_back(Pair("collateralIndex", (int)dmn->nCollateralIndex));
|
||||
UniValue stateObj;
|
||||
dmn->pdmnState->ToJson(stateObj);
|
||||
mnObj.push_back(Pair("dmnState", stateObj));
|
||||
}
|
||||
mnObj.push_back(Pair("state", activeMasternodeManager->GetStateString()));
|
||||
mnObj.push_back(Pair("status", activeMasternodeManager->GetStatus()));
|
||||
} else {
|
||||
CMasternode mn;
|
||||
if(mnodeman.Get(activeMasternodeInfo.outpoint, mn)) {
|
||||
mnObj.push_back(Pair("payee", CBitcoinAddress(mn.keyIDCollateralAddress).ToString()));
|
||||
}
|
||||
|
||||
mnObj.push_back(Pair("status", legacyActiveMasternodeManager.GetStatus()));
|
||||
}
|
||||
return mnObj;
|
||||
}
|
||||
|
||||
@ -786,6 +893,8 @@ UniValue masternode(const JSONRPCRequest& request)
|
||||
#endif // ENABLE_WALLET
|
||||
} else if (strCommand == "genkey") {
|
||||
return masternode_genkey(request);
|
||||
} else if (strCommand == "info") {
|
||||
return masternode_info(request);
|
||||
} else if (strCommand == "list-conf") {
|
||||
return masternode_list_conf(request);
|
||||
#ifdef ENABLE_WALLET
|
||||
|
Loading…
Reference in New Issue
Block a user