diff --git a/configure.ac b/configure.ac index 4084b11c99..681a76bd72 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 1) -define(_CLIENT_VERSION_REVISION, 1) +define(_CLIENT_VERSION_REVISION, 2) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_RC, 0) define(_CLIENT_VERSION_IS_RELEASE, true) diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 0c4dd08b73..c984e5bf12 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -40,7 +40,7 @@ void CActiveMasternode::ManageStatus() pmn = mnodeman.Find(pubKeyMasternode); if (pmn != nullptr) { pmn->Check(); - if (pmn->IsEnabled() && pmn->protocolVersion == PROTOCOL_VERSION) + if (pmn->IsEnabled()) EnableHotColdMasterNode(pmn->vin, pmn->addr); } } diff --git a/src/activemasternodeconfig.cpp b/src/activemasternodeconfig.cpp index 1a6c42c94a..883ef6133e 100644 --- a/src/activemasternodeconfig.cpp +++ b/src/activemasternodeconfig.cpp @@ -14,28 +14,18 @@ CActiveMasternodeConfig activeMasternodeConfig; -CActiveMasternodeConfig::CActiveMasternodeEntry& CActiveMasternodeConfig::add(std::string strAlias, std::string strMasterNodePrivKey) +void CActiveMasternodeConfig::add(std::string strAlias, std::string strMasterNodePrivKey) { CActiveMasternodeEntry cme(strAlias, strMasterNodePrivKey); vEntries.push_back(cme); - return vEntries.back(); } -void CActiveMasternodeConfig::remove(std::string strAlias) +bool CActiveMasternodeConfig::Load(std::string& strErr) { - int pos = -1; - for (int i = 0; i < ((int)vEntries.size()); ++i) { - CActiveMasternodeEntry e = vEntries[i]; - if (e.strAlias == strAlias) { - pos = i; - break; - } - } - vEntries.erase(vEntries.begin() + pos); -} + auto backup = vEntries; + + vEntries.clear(); -bool CActiveMasternodeConfig::read(std::string& strErr) -{ int linenumber = 1; fs::path pathActiveMasternodeConfigFile = GetActiveMasternodeConfigFile(); fs::ifstream streamConfig(pathActiveMasternodeConfigFile); @@ -73,6 +63,7 @@ bool CActiveMasternodeConfig::read(std::string& strErr) strErr = _("Could not parse activemasternode.conf") + "\n" + strprintf(_("Line: %d"), linenumber) + "\n\"" + line + "\""; streamConfig.close(); + vEntries = backup; return false; } } @@ -80,6 +71,7 @@ bool CActiveMasternodeConfig::read(std::string& strErr) if (strAlias.empty()) { strErr = _("alias cannot be empty in activemasternode.conf"); streamConfig.close(); + vEntries = backup; return false; } @@ -89,3 +81,28 @@ bool CActiveMasternodeConfig::read(std::string& strErr) streamConfig.close(); return true; } + +uint256 CActiveMasternodeConfig::GetFileHash() { + fs::path pathActiveMasternodeConfigFile = GetActiveMasternodeConfigFile(); + fs::ifstream streamConfig(pathActiveMasternodeConfigFile); + + if (!streamConfig.good()) { + return UINT256_ZERO; + } + + //get length of file + streamConfig.seekg(0, streamConfig.end); + size_t length = streamConfig.tellg(); + streamConfig.seekg(0, streamConfig.beg); + + //read file + if (length > 0) { + std::vector buffer; + buffer.resize(length); + streamConfig.read(&buffer[0], length); + + return Hash(&buffer[0], &buffer[0] + length); + } + + return UINT256_ZERO; +} diff --git a/src/activemasternodeconfig.h b/src/activemasternodeconfig.h index 9276692001..0e1afe300f 100644 --- a/src/activemasternodeconfig.h +++ b/src/activemasternodeconfig.h @@ -7,6 +7,7 @@ #ifndef SRC_ACTIVEMASTERNODECONFIG_H_ #define SRC_ACTIVEMASTERNODECONFIG_H_ +#include "uint256.h" #include #include @@ -29,17 +30,16 @@ class CActiveMasternodeConfig } }; - void clear(); - bool read(std::string& strErr); - CActiveMasternodeConfig::CActiveMasternodeEntry& add(std::string strAlias, std::string strMasterNodePrivKey); - void remove(std::string strAlias); + bool Load(std::string& strErr); + uint256 GetFileHash(); - std::vector& getEntries() + std::vector& Entries() { return vEntries; } private: std::vector vEntries; + void add(std::string strAlias, std::string strMasterNodePrivKey); }; #endif /* SRC_ACTIVEMASTERNODECONFIG_H_ */ diff --git a/src/activemasternodeman.cpp b/src/activemasternodeman.cpp index f942747949..ac7ad9bec1 100644 --- a/src/activemasternodeman.cpp +++ b/src/activemasternodeman.cpp @@ -11,17 +11,106 @@ #include void CActiveMasternodeMan::ManageStatus() { + + LOCK(cs); + + std::string strErr; + if(!Reload(strErr)) { + LogPrintf("CActiveMasternodeMan::ManageStatus() - %s\n", strErr); + } + for(auto& amn : vActiveMasternodes) { amn.ManageStatus(); } } void CActiveMasternodeMan::ResetStatus() { + + LOCK(cs); + + std::string strErr; + if(!Reload(strErr)) { + LogPrintf("CActiveMasternodeMan::ManageStatus() - %s\n", strErr); + } + for(auto& amn : vActiveMasternodes) { amn.ResetStatus(); } } -void CActiveMasternodeMan::Add(CActiveMasternode activeMasternode) { - vActiveMasternodes.push_back(activeMasternode); +bool CActiveMasternodeMan::Add(CActiveMasternodeConfig::CActiveMasternodeEntry ame, std::string& strErr) { + + LOCK(cs); + + auto strAlias = ame.strAlias; + auto strMasterNodePrivKey = ame.strMasterNodePrivKey; + + if (strAlias.empty()) { + strErr = _("alias cannot be empty in activemasternode.conf"); + return false; + } + + CActiveMasternode amn; + + amn.strAlias = strAlias; + amn.strMasterNodePrivKey = strMasterNodePrivKey; + + CKey key; + CPubKey pubkey; + + if (!CMessageSigner::GetKeysFromSecret(amn.strMasterNodePrivKey, key, pubkey)) { + strErr = _("Invalid masternodeprivkey. Please see documenation."); + return false; + } + + amn.pubKeyMasternode = pubkey; + + vActiveMasternodes.push_back(amn); + + return true; } + +bool CActiveMasternodeMan::Load(std::string& strErr) { + + LOCK(cs); + + if (!activeMasternodeConfig.Load(strErr)) return false; + + fileHash = activeMasternodeConfig.GetFileHash(); + + for(auto& ame : activeMasternodeConfig.Entries()) { + if(!Add(ame, strErr)) return false; + } + + return true; +} + +bool CActiveMasternodeMan::Reload(std::string& strErr) { + + LOCK(cs); + + auto hash = activeMasternodeConfig.GetFileHash(); + + if(fileHash != hash) { + if (!activeMasternodeConfig.Load(strErr)) return false; + + auto backup = vActiveMasternodes; + + vActiveMasternodes.clear(); + for(auto& ame : activeMasternodeConfig.Entries()) { + if(!Add(ame, strErr)) { + vActiveMasternodes.clear(); + vActiveMasternodes = backup; + return false; + } + } + + fileHash = hash; + + ResetStatus(); + + return true; + } + + return true; +} \ No newline at end of file diff --git a/src/activemasternodeman.h b/src/activemasternodeman.h index 39d796926b..c53fca8960 100644 --- a/src/activemasternodeman.h +++ b/src/activemasternodeman.h @@ -8,6 +8,7 @@ #define ACTIVEMASTERNODES_H #include "activemasternode.h" +#include "activemasternodeconfig.h" #include @@ -16,12 +17,21 @@ class CActiveMasternodeMan { private: std::vector vActiveMasternodes; + uint256 fileHash = UINT256_ZERO; + // critical section to protect the inner data structures + mutable RecursiveMutex cs; public: /// Manage status of all Masternodes void ManageStatus(); void ResetStatus(); std::vector& GetActiveMasternodes() { return vActiveMasternodes; } - void Add(CActiveMasternode activeMasternode); + bool Add(CActiveMasternodeConfig::CActiveMasternodeEntry ame, std::string& strErr); + bool Add(std::string strAlias, std::string strMasterNodePrivKey, std::string& strErr) { + return Add(CActiveMasternodeConfig::CActiveMasternodeEntry(strAlias, strMasterNodePrivKey), strErr); + } + bool Load(std::string& strErr); + bool Reload(std::string& strErr); + std::size_t Count() { return vActiveMasternodes.size(); } }; #endif //ACTIVEMASTERNODES_H diff --git a/src/chain.cpp b/src/chain.cpp index 29b8c46c07..97856aae99 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -7,6 +7,7 @@ #include "chain.h" #include "masternode.h" +#include "masternodeman.h" #include "legacy/stakemodifier.h" // for ComputeNextStakeModifier @@ -250,13 +251,14 @@ CScript* CBlockIndex::GetPaidPayee() if(paidPayee == nullptr || paidPayee->empty()) { CBlock block; if (nHeight <= chainActive.Height() && ReadBlockFromDisk(block, this)) { - const auto& tx = block.vtx[block.IsProofOfWork() ? 0 : 1]; auto amount = CMasternode::GetMasternodePayment(nHeight); - - for (const CTxOut& out : tx.vout) { - if (out.nValue == amount - ) { - paidPayee = new CScript(out.scriptPubKey); + auto mnpayee = block.GetPaidPayee(nHeight, amount); + + if(!mnpayee.empty()) { + paidPayee = new CScript(mnpayee); + auto pmn = mnodeman.Find(mnpayee); + if(pmn) { + pmn->lastPaid = GetBlockTime(); } } } diff --git a/src/init.cpp b/src/init.cpp index 1c5b995c1e..64a5ebe0d3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -917,42 +917,6 @@ void InitLogging() LogPrintf("DashDiamond version %s (%s)\n", version_string, CLIENT_DATE); } -bool AppInitActiveMasternode(std::string strAlias, std::string strMasterNodePrivKey) -{ - if (strAlias.empty()) { - return UIError(_("activemasternode alias cannot be empty")); - } - - CActiveMasternode activeMasternode; - - activeMasternode.strAlias = strAlias; - - activeMasternode.strMasterNodePrivKey = strMasterNodePrivKey; - - std::string errorMessage; - - CKey key; - CPubKey pubkey; - - if (!CMessageSigner::GetKeysFromSecret(activeMasternode.strMasterNodePrivKey, key, pubkey)) { - return UIError(_("Invalid masternodeprivkey. Please see documenation.")); - } - - activeMasternode.pubKeyMasternode = pubkey; - - amnodeman.Add(activeMasternode); - - return true; -} - -bool AppInitActiveMasternode(CActiveMasternodeConfig::CActiveMasternodeEntry activeMasternodeEntry) -{ - return AppInitActiveMasternode( - activeMasternodeEntry.strAlias, - activeMasternodeEntry.strMasterNodePrivKey - ); -} - /** Initialize dashdiamond. * @pre Parameters should be parsed and config file should be read. */ @@ -1726,19 +1690,15 @@ bool AppInit2() if (fMasterNode) { LogPrintf("IS MASTER NODE\n"); - //legacy - if(!GetArg("-masternodeprivkey", "").empty()) - { - if(!AppInitActiveMasternode("legacy", GetArg("-masternodeprivkey", ""))) return false; - } else { - // multinode - std::string strErr; - if (!activeMasternodeConfig.read(strErr)) { - return UIError(strprintf(_("Error reading active masternode configuration file: %s"), strErr)); - } + std::string strErr; + if (!amnodeman.Load(strErr)) { + return UIError(strprintf(_("Error reading active masternode configuration file: %s"), strErr)); + } - for(auto& ame : activeMasternodeConfig.getEntries()) { - if(!AppInitActiveMasternode(ame)) return false; + // legacy + if (amnodeman.Count() == 0 && !GetArg("-masternodeprivkey", "").empty()) { + if (!amnodeman.Add("legacy", GetArg("-masternodeprivkey", ""), strErr)) { + return UIError(strprintf(_("Error reading masternodeprivkey: %s"), strErr)); } } } diff --git a/src/main.cpp b/src/main.cpp index 1f5fc7c1f4..580681dac0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1959,6 +1959,17 @@ DisconnectResult DisconnectBlock(CBlock& block, CBlockIndex* pindex, CCoinsViewC // move best block pointer to prevout block view.SetBestBlock(pindex->pprev->GetBlockHash()); + // Clean lastPaid + auto amount = CMasternode::GetMasternodePayment(pindex->nHeight); + auto paidPayee = block.GetPaidPayee(pindex->nHeight, amount); + if(!paidPayee.empty()) { + auto pmn = mnodeman.Find(paidPayee); + + if(pmn) { + pmn->lastPaid = INT64_MAX; + } + } + return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; } @@ -2189,6 +2200,17 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3; LogPrint(BCLog::BENCH, " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeCallbacks * 0.000001); + + // Fill lastPaid + auto amount = CMasternode::GetMasternodePayment(pindex->nHeight); + auto paidPayee = block.GetPaidPayee(pindex->nHeight, amount); + if(!paidPayee.empty()) { + auto pmn = mnodeman.Find(paidPayee); + + if(pmn) { + pmn->lastPaid = pindex->GetBlockTime(); + } + } return true; } diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index a033da1b76..adf5c2af20 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -180,12 +180,6 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError) return false; } - if (pmn->protocolVersion < ActiveProtocol()) { - strError = strprintf("Masternode protocol too old %d - req %d", pmn->protocolVersion, ActiveProtocol()); - LogPrint(BCLog::MASTERNODE,"CMasternodePaymentWinner::IsValid - %s\n", strError); - return false; - } - if (sporkManager.IsSporkActive(SPORK_102_FORCE_ENABLED_MASTERNODE)) { if (pmn->Status() != "ENABLED") { strError = strprintf("Masternode is not in ENABLED state - Status(): %d", pmn->Status()); @@ -194,7 +188,7 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError) } } - int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol()); + int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100); if (n > MNPAYMENTS_SIGNATURES_TOTAL) { //It's common to have masternodes mistakenly think they are in the top 10 @@ -278,10 +272,18 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight) // fails if spork 8 is enabled and // spork 113 is disabled or current time is outside the reconsider window if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) { - if (!sporkManager.IsSporkActive(SPORK_113_RECONSIDER_WINDOW_ENFORCEMENT) || - (t / MINUTE_IN_SECONDS) % 10 != reconsiderWindowMin) { + if (!sporkManager.IsSporkActive(SPORK_113_RECONSIDER_WINDOW_ENFORCEMENT)) + { + return false; + } + + if ((t / MINUTE_IN_SECONDS) % 10 != reconsiderWindowMin) + { return false; } + + LogPrint(BCLog::MASTERNODE,"Masternode payment enforcement reconsidered, accepting block\n"); + return true; } LogPrint(BCLog::MASTERNODE,"Masternode payment enforcement is disabled, accepting block\n"); @@ -694,14 +696,8 @@ bool CMasternodeBlockPayees::IsTransactionValidV2(const CTransaction& txNew, int return result; } else { LogPrint(BCLog::MASTERNODE, "CMasternodePayments::IsTransactionValid - Missing required payment of %s\n", FormatMoney(requiredMasternodePayment).c_str()); - } - auto t = GetTime(); - // returns true if it is inside the reconsider window - if (found && - sporkManager.IsSporkActive(SPORK_113_RECONSIDER_WINDOW_ENFORCEMENT) && - (t / MINUTE_IN_SECONDS) % 10 == reconsiderWindowMin) { - return true; + return false; } return false; @@ -759,6 +755,10 @@ bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlo return mnbp.IsTransactionValid(txNew, nBlockHeight); } + if (sporkManager.IsSporkActive(SPORK_112_MASTERNODE_LAST_PAID_V2)) { // if voting is disabled, try again + return mnbp.IsTransactionValid(txNew, nBlockHeight); + } + return true; } @@ -807,7 +807,7 @@ void CMasternodePayments::ProcessBlock(int nBlockHeight) //reference node - hybrid mode - int n = mnodeman.GetMasternodeRank(*(activeMasternode.vin), nBlockHeight - 100, ActiveProtocol()); + int n = mnodeman.GetMasternodeRank(*(activeMasternode.vin), nBlockHeight - 100); if (n == -1 || n == INT_MAX) { LogPrint(BCLog::MASTERNODE, "CMasternodePayments::ProcessBlock - Unknown Masternode\n"); diff --git a/src/masternode.cpp b/src/masternode.cpp index 0b43d8bf7c..a611d98819 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -304,12 +304,16 @@ int64_t CMasternode::GetLastPaidV1(CBlockIndex* pblockindex, const CScript& mnpa int64_t CMasternode::GetLastPaidV2(CBlockIndex* pblockindex, const CScript& mnpayee) { + if(lastPaid != INT64_MAX) return lastPaid; + int max_depth = mnodeman.CountEnabled() * 2; // go a little bit further than V1 + for (int n = 0; n < max_depth; n++) { auto paidpayee = pblockindex->GetPaidPayee(); if(paidpayee && mnpayee == *paidpayee) { - return pblockindex->nTime; // doesn't need the offset because it is deterministically read from the blockchain + lastPaid = pblockindex->nTime; + return lastPaid; } pblockindex = pblockindex->pprev; @@ -319,7 +323,8 @@ int64_t CMasternode::GetLastPaidV2(CBlockIndex* pblockindex, const CScript& mnpa } } - return 0; + lastPaid = 0; + return lastPaid; } int64_t CMasternode::GetLastPaid() @@ -638,11 +643,6 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos) if(lastPing.IsNull() || !lastPing.CheckAndUpdate(nDos, false, true)) return false; - if (protocolVersion < ActiveProtocol()) { - LogPrint(BCLog::MASTERNODE, "mnb - ignoring outdated Masternode %s protocol version %d\n", vin.prevout.ToStringShort(), protocolVersion); - return false; - } - CScript pubkeyScript; pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID()); @@ -808,8 +808,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS) // if it matches our Masternode privkey, then we've been remotely activated for (auto& activeMasternode : amnodeman.GetActiveMasternodes()) { - if (pubKeyMasternode == activeMasternode.pubKeyMasternode && - protocolVersion == PROTOCOL_VERSION) { + if (pubKeyMasternode == activeMasternode.pubKeyMasternode) { activeMasternode.EnableHotColdMasterNode(vin, addr); } } @@ -907,7 +906,7 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled, bool fChec LogPrint(BCLog::MNPING, "%s: New Ping - %s - %s - %lli\n", __func__, GetHash().ToString(), blockHash.ToString(), sigTime); - if (isMasternodeFound && pmn->protocolVersion >= ActiveProtocol()) { + if (isMasternodeFound) { if (fRequireEnabled && !pmn->IsEnabled()) return false; // update only if there is no known ping for this masternode or diff --git a/src/masternode.h b/src/masternode.h index 87c16fa927..1402b7852f 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -144,7 +144,7 @@ class CMasternode : public CSignedMessage int nScanningErrorCount; int nLastScanningErrorBlockHeight; CMasternodePing lastPing; - uint64_t lastPaid; + int64_t lastPaid = INT64_MAX; CMasternode(); CMasternode(const CMasternode& other); diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index aec87e31f3..e539b3d3f2 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -274,8 +274,7 @@ void CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval) while (it != vMasternodes.end()) { if ((**it).activeState == CMasternode::MASTERNODE_REMOVE || (**it).activeState == CMasternode::MASTERNODE_VIN_SPENT || - (forceExpiredRemoval && (**it).activeState == CMasternode::MASTERNODE_EXPIRED) || - (**it).protocolVersion < ActiveProtocol()) { + (forceExpiredRemoval && (**it).activeState == CMasternode::MASTERNODE_EXPIRED)) { LogPrint(BCLog::MASTERNODE, "CMasternodeMan: Removing inactive Masternode %s - %i now\n", (**it).vin.prevout.ToStringShort(), size() - 1); //erase all of the broadcasts we've seen from this vin @@ -404,16 +403,12 @@ void CMasternodeMan::Clear() int CMasternodeMan::stable_size () { int nStable_size = 0; - int nMinProtocol = ActiveProtocol(); int64_t nMasternode_Min_Age = MN_WINNER_MINIMUM_AGE; int64_t nMasternode_Age = 0; LOCK2(cs_main, cs); for (auto mn : vMasternodes) { - if (mn->protocolVersion < nMinProtocol) { - continue; // Skip obsolete versions - } if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) && sporkManager.IsSporkActive(SPORK_108_FORCE_MASTERNODE_MIN_AGE)) { @@ -432,23 +427,22 @@ int CMasternodeMan::stable_size () return nStable_size; } -int CMasternodeMan::CountEnabled(int protocolVersion) +int CMasternodeMan::CountEnabled() { int i = 0; - protocolVersion = protocolVersion == -1 ? ActiveProtocol() : protocolVersion; LOCK2(cs_main, cs); for (auto mn : vMasternodes) { mn->Check(); - if (mn->protocolVersion < protocolVersion || !mn->IsEnabled()) continue; + if (!mn->IsEnabled()) continue; i++; } return i; } -void CMasternodeMan::CountNetworks(int protocolVersion, int& ipv4, int& ipv6, int& onion) +void CMasternodeMan::CountNetworks(int& ipv4, int& ipv6, int& onion) { LOCK2(cs_main, cs); @@ -563,9 +557,6 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight mn->Check(); if (!mn->IsEnabled()) continue; - // //check protocol version - if (mn->protocolVersion < ActiveProtocol()) continue; - //it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it if (masternodePayments.IsScheduled(*mn, nBlockHeight)) continue; @@ -626,19 +617,17 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight return pBestMasternode; } -CMasternode* CMasternodeMan::GetCurrentMasterNode(int mod, int64_t nBlockHeight, int minProtocol) +CMasternode* CMasternodeMan::GetCurrentMasterNode(int mod, int64_t nBlockHeight) { int64_t score = 0; CMasternode* winner = NULL; - if(minProtocol == 0) minProtocol = ActiveProtocol(); - LOCK2(cs_main, cs); // scan for winner for (auto mn : vMasternodes) { mn->Check(); - if (mn->protocolVersion < minProtocol || !mn->IsEnabled()) continue; + if (!mn->IsEnabled()) continue; // calculate the score for each Masternode uint256 n = mn->CalculateScore(mod, nBlockHeight); @@ -654,7 +643,7 @@ CMasternode* CMasternodeMan::GetCurrentMasterNode(int mod, int64_t nBlockHeight, return winner; } -int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, int minProtocol) +int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight) { std::vector> vecMasternodeScores; int64_t nMasternode_Min_Age = MN_WINNER_MINIMUM_AGE; @@ -673,11 +662,6 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, in // scan for winner for (auto mn : vMasternodes) { - if (mn->protocolVersion < minProtocol) { - LogPrint(BCLog::MASTERNODE,"Skipping Masternode with obsolete version %d\n", mn->protocolVersion); - continue; // Skip obsolete versions - } - if (sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) && sporkManager.IsSporkActive(SPORK_108_FORCE_MASTERNODE_MIN_AGE)) { @@ -710,7 +694,7 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, in return defaultValue; } -std::vector > CMasternodeMan::GetMasternodeRanks(int64_t nBlockHeight, int minProtocol) +std::vector> CMasternodeMan::GetMasternodeRanks(int64_t nBlockHeight) { std::vector > vecMasternodeScores; std::vector > vecMasternodeRanks; @@ -732,8 +716,6 @@ std::vector > CMasternodeMan::GetMasternodeRanks(int // scan for winner for (CMasternode& mn : vmn) { - if (mn.protocolVersion < minProtocol) continue; - if (!mn.IsEnabled()) { vecMasternodeScores.push_back(std::make_pair(INT_MAX, mn)); continue; diff --git a/src/masternodeman.h b/src/masternodeman.h index fa6883c3b6..b6c8a96071 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -155,9 +155,9 @@ class CMasternodeMan /// Clear Masternode vector void Clear(); - int CountEnabled(int protocolVersion = -1); + int CountEnabled(); - void CountNetworks(int protocolVersion, int& ipv4, int& ipv6, int& onion); + void CountNetworks(int& ipv4, int& ipv6, int& onion); void DsegUpdate(CNode* pnode); @@ -189,7 +189,7 @@ class CMasternodeMan } /// Get the current winner for this block - CMasternode* GetCurrentMasterNode(int mod = 1, int64_t nBlockHeight = 0, int minProtocol = 0); + CMasternode* GetCurrentMasterNode(int mod = 1, int64_t nBlockHeight = 0); std::vector GetFullMasternodeVector() { @@ -207,8 +207,8 @@ class CMasternodeMan return result; } - std::vector > GetMasternodeRanks(int64_t nBlockHeight, int minProtocol = 0); - int GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, int minProtocol = 0); + std::vector > GetMasternodeRanks(int64_t nBlockHeight); + int GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); diff --git a/src/net.cpp b/src/net.cpp index 3e68629cb5..d342e5c8d7 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1083,6 +1083,17 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { } } + // close obsolete nodes' connection + { + LOCK(cs_vNodes); + for (CNode* pnode : vNodes) { + if (pnode->nVersion > 0 && pnode->nVersion < ActiveProtocol()) { + pnode->fDisconnect = true; + pnode->CloseSocketDisconnect(); + } + } + } + if (hSocket != INVALID_SOCKET) if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) LogPrintf("Warning: Unknown socket family\n"); diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 50313aaacb..f25de3e7b7 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -35,6 +35,17 @@ uint256 CBlockHeader::GetHash() const return SerializeHash(*this); // nVersion >= 4 } +CScript CBlock::GetPaidPayee(int nHeight, CAmount nAmount) const +{ + const auto& tx = vtx[IsProofOfWork() ? 0 : 1]; + + for (const CTxOut& out : tx.vout) { + if (out.nValue == nAmount) return out.scriptPubKey; + } + + return CScript(); +} + std::string CBlock::ToString() const { std::stringstream s; diff --git a/src/primitives/block.h b/src/primitives/block.h index d3aed9312f..40c22dc8de 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -144,6 +144,8 @@ class CBlock : public CBlockHeader return !IsProofOfStake(); } + CScript GetPaidPayee(int nHeight, CAmount nAmount) const; + std::string ToString() const; void print() const; }; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 331fe5b59a..1278952c46 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -78,7 +78,7 @@ int ClientModel::getNumConnections(unsigned int flags) const QString ClientModel::getMasternodeCountString() const { int ipv4 = 0, ipv6 = 0, onion = 0; - mnodeman.CountNetworks(ActiveProtocol(), ipv4, ipv6, onion); + mnodeman.CountNetworks(ipv4, ipv6, onion); int nUnknown = mnodeman.size() - ipv4 - ipv6 - onion; if(nUnknown < 0) nUnknown = 0; return tr("Total: %1 (IPv4: %2 / IPv6: %3 / Tor: %4 / Unknown: %5)").arg(QString::number((int)mnodeman.size())).arg(QString::number((int)ipv4)).arg(QString::number((int)ipv6)).arg(QString::number((int)onion)).arg(QString::number((int)nUnknown)); diff --git a/src/qt/pivx/masternodewizarddialog.cpp b/src/qt/pivx/masternodewizarddialog.cpp index 657e6448e2..ceb657c9ca 100644 --- a/src/qt/pivx/masternodewizarddialog.cpp +++ b/src/qt/pivx/masternodewizarddialog.cpp @@ -257,7 +257,7 @@ bool MasterNodeWizardDialog::createMN() int indexOut = -1; for (int i=0; i < (int)walletTx->vout.size(); i++) { CTxOut& out = walletTx->vout[i]; - if (out.nValue == CMasternode::CMasternode::GetNextWeekMasternodeCollateral()) { + if (out.nValue == CMasternode::GetNextWeekMasternodeCollateral()) { indexOut = i; break; } diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 9fbef76161..8bf46933df 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -128,7 +128,7 @@ UniValue getmasternodecount (const JSONRPCRequest& request) if (nChainHeight < 0) return "unknown"; int nCount = mnodeman.GetNextMasternodeInQueueCount(nChainHeight); - mnodeman.CountNetworks(ActiveProtocol(), ipv4, ipv6, onion); + mnodeman.CountNetworks(ipv4, ipv6, onion); obj.push_back(Pair("total", mnodeman.size())); obj.push_back(Pair("stable", mnodeman.stable_size())); @@ -514,6 +514,64 @@ UniValue listmasternodeconf (const JSONRPCRequest& request) return ret; } +UniValue getactivemasternodecount (const JSONRPCRequest& request) +{ + if (request.fHelp || (request.params.size() > 0)) + throw std::runtime_error( + "getactivemasternodecount\n" + "\nGet active masternode count values\n" + + "\nResult:\n" + "{\n" + " \"total\": n, (numeric) Total masternodes\n" + " \"initial\": n, (numeric) Initial state masternodes\n" + " \"syncing\": n, (numeric) Syncing masternodes\n" + " \"not_capable\": n, (numeric) Not capable masternodes\n" + " \"started\": n, (numeric) Started masternodes\n" + "}\n" + + "\nExamples:\n" + + HelpExampleCli("getactivemasternodecount", "") + HelpExampleRpc("getactivemasternodecount", "")); + + if (!fMasterNode) + throw JSONRPCError(RPC_MISC_ERROR, _("This is not a masternode.")); + + int total = 0; + int initial = 0; + int syncing = 0; + int not_capable = 0; + int started = 0; + + for (auto& amn : amnodeman.GetActiveMasternodes()) { + switch(amn.GetStatus()) { + case ACTIVE_MASTERNODE_INITIAL: + initial++; + break; + case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: + syncing++; + break; + case ACTIVE_MASTERNODE_NOT_CAPABLE: + not_capable++; + break; + case ACTIVE_MASTERNODE_STARTED: + started++; + break; + } + total++; + } + + UniValue obj(UniValue::VOBJ); + + obj.push_back(Pair("total", total)); + obj.push_back(Pair("initial", initial)); + obj.push_back(Pair("syncing", syncing)); + obj.push_back(Pair("not_capable", not_capable)); + obj.push_back(Pair("started", started)); + + return obj; +} + + UniValue getmasternodestatus(const JSONRPCRequest& request) { if (request.fHelp || (request.params.size() != 0)) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 5c007ec7b7..c447e07855 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -370,6 +370,7 @@ static const CRPCCommand vRPCCommands[] = {"dashdiamond", "createmasternodekey", &createmasternodekey, true }, {"dashdiamond", "getmasternodeoutputs", &getmasternodeoutputs, true }, {"dashdiamond", "listmasternodeconf", &listmasternodeconf, true }, + {"dashdiamond", "getactivemasternodecount", &getactivemasternodecount, true }, {"dashdiamond", "getmasternodestatus", &getmasternodestatus, true }, {"dashdiamond", "getmasternodewinners", &getmasternodewinners, true }, {"dashdiamond", "getmasternodescores", &getmasternodescores, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index e9d26cf22b..2fb01a2617 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -260,6 +260,7 @@ extern UniValue startmasternode(const JSONRPCRequest& request); extern UniValue createmasternodekey(const JSONRPCRequest& request); extern UniValue getmasternodeoutputs(const JSONRPCRequest& request); extern UniValue listmasternodeconf(const JSONRPCRequest& request); +extern UniValue getactivemasternodecount(const JSONRPCRequest& request); extern UniValue getmasternodestatus(const JSONRPCRequest& request); extern UniValue getmasternodewinners(const JSONRPCRequest& request); extern UniValue getmasternodescores(const JSONRPCRequest& request); diff --git a/src/version.h b/src/version.h index 4e129a3125..91e78d5a82 100644 --- a/src/version.h +++ b/src/version.h @@ -12,7 +12,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 70103; +static const int PROTOCOL_VERSION = 70104; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209;