From ea434a1ed811c69e93594ec13880ac71441cd5bf Mon Sep 17 00:00:00 2001 From: furszy Date: Sun, 18 Oct 2020 23:11:48 -0300 Subject: [PATCH 1/2] CMasternodeMan::GetMasternodeRanks removed unneeded MN extra validations and totally unnecessary extra vector load. As this function is only used in listmasternodes RPC command, the checks are redundant, the MN thread only should check and update `vMasternodes`, removing any invalid masternode. --- src/masternodeman.cpp | 42 ++++++++++++++---------------------------- src/masternodeman.h | 4 ++-- src/rpc/masternode.cpp | 7 ++++--- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 66bf64f08c8c0..3c975d2b74bad 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -616,41 +616,27 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, in return -1; } -std::vector > CMasternodeMan::GetMasternodeRanks(int64_t nBlockHeight, int minProtocol) +std::vector> CMasternodeMan::GetMasternodeRanks(int nBlockHeight) { - std::vector > vecMasternodeScores; - std::vector > vecMasternodeRanks; - + std::vector> vecMasternodeScores; const uint256& hash = GetHashAtHeight(nBlockHeight - 1); // height outside range - if (!hash) return vecMasternodeRanks; - - // scan for winner - for (CMasternode& mn : vMasternodes) { - mn.Check(); - - if (mn.protocolVersion < minProtocol) continue; + if (!hash) return vecMasternodeScores; + { + LOCK(cs); + // scan for winner + for (CMasternode& mn : vMasternodes) { + if (!mn.IsEnabled()) { + vecMasternodeScores.emplace_back(9999, mn); + continue; + } - if (!mn.IsEnabled()) { - vecMasternodeScores.emplace_back(9999, mn); - continue; + int64_t n2 = mn.CalculateScore(hash).GetCompact(false); + vecMasternodeScores.emplace_back(n2, mn); } - - uint256 n = mn.CalculateScore(hash); - int64_t n2 = n.GetCompact(false); - - vecMasternodeScores.emplace_back(n2, mn); } - sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN()); - - int rank = 0; - for (PAIRTYPE(int64_t, CMasternode) & s : vecMasternodeScores) { - rank++; - vecMasternodeRanks.emplace_back(rank, s.second); - } - - return vecMasternodeRanks; + return vecMasternodeScores; } void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) diff --git a/src/masternodeman.h b/src/masternodeman.h index 71263c98f136c..ba52ce90ef9a7 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -146,8 +146,8 @@ class CMasternodeMan Check(); return vMasternodes; } - - std::vector > GetMasternodeRanks(int64_t nBlockHeight, int minProtocol = 0); + // Retrieve the known masternodes ordered by scoring without checking them. (Only used for listmasternodes RPC call) + std::vector> GetMasternodeRanks(int nBlockHeight); int GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, int minProtocol = 0, bool fOnlyActive = true); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 4854762d1ec2b..2b061d25bfb49 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -81,8 +81,9 @@ UniValue listmasternodes(const JSONRPCRequest& request) int nHeight = WITH_LOCK(cs_main, return chainActive.Height()); if (nHeight < 0) return "[]"; - std::vector > vMasternodeRanks = mnodeman.GetMasternodeRanks(nHeight); - for (PAIRTYPE(int, CMasternode) & s : vMasternodeRanks) { + std::vector> vMasternodeRanks = mnodeman.GetMasternodeRanks(nHeight); + for (int pos=0; pos < (int) vMasternodeRanks.size(); pos++) { + const auto& s = vMasternodeRanks[pos]; UniValue obj(UniValue::VOBJ); std::string strVin = s.second.vin.prevout.ToStringShort(); std::string strTxHash = s.second.vin.prevout.hash.ToString(); @@ -103,7 +104,7 @@ UniValue listmasternodes(const JSONRPCRequest& request) LookupHost(strHost.c_str(), node, false); std::string strNetwork = GetNetworkName(node.GetNetwork()); - obj.pushKV("rank", (strStatus == "ENABLED" ? s.first : 0)); + obj.pushKV("rank", (strStatus == "ENABLED" ? pos : 0)); obj.pushKV("network", strNetwork); obj.pushKV("txhash", strTxHash); obj.pushKV("outidx", (uint64_t)oIdx); From 872da916d9ac2725483bb5528add3d7f3beddbdf Mon Sep 17 00:00:00 2001 From: furszy Date: Sun, 18 Oct 2020 23:26:30 -0300 Subject: [PATCH 2/2] Speedup listmasternodes removing a redundant for loop over every MN on the mnnodeman. listmasternodes first calls GetMasternodeRanks, which loops over the MN list, then was calling `mnodeman.Find` which loops again over the MN list for absolutely no reason. --- src/rpc/masternode.cpp | 62 ++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 2b061d25bfb49..ee37bcda8a2eb 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -85,39 +85,37 @@ UniValue listmasternodes(const JSONRPCRequest& request) for (int pos=0; pos < (int) vMasternodeRanks.size(); pos++) { const auto& s = vMasternodeRanks[pos]; UniValue obj(UniValue::VOBJ); - std::string strVin = s.second.vin.prevout.ToStringShort(); - std::string strTxHash = s.second.vin.prevout.hash.ToString(); - uint32_t oIdx = s.second.vin.prevout.n; - - CMasternode* mn = mnodeman.Find(s.second.vin); - - if (mn != NULL) { - if (strFilter != "" && strTxHash.find(strFilter) == std::string::npos && - mn->Status().find(strFilter) == std::string::npos && - EncodeDestination(mn->pubKeyCollateralAddress.GetID()).find(strFilter) == std::string::npos) continue; - - std::string strStatus = mn->Status(); - std::string strHost; - int port; - SplitHostPort(mn->addr.ToString(), port, strHost); - CNetAddr node; - LookupHost(strHost.c_str(), node, false); - std::string strNetwork = GetNetworkName(node.GetNetwork()); - - obj.pushKV("rank", (strStatus == "ENABLED" ? pos : 0)); - obj.pushKV("network", strNetwork); - obj.pushKV("txhash", strTxHash); - obj.pushKV("outidx", (uint64_t)oIdx); - obj.pushKV("pubkey", HexStr(mn->pubKeyMasternode)); - obj.pushKV("status", strStatus); - obj.pushKV("addr", EncodeDestination(mn->pubKeyCollateralAddress.GetID())); - obj.pushKV("version", mn->protocolVersion); - obj.pushKV("lastseen", (int64_t)mn->lastPing.sigTime); - obj.pushKV("activetime", (int64_t)(mn->lastPing.sigTime - mn->sigTime)); - obj.pushKV("lastpaid", (int64_t)mn->GetLastPaid()); + CMasternode mn = s.second; + + std::string strVin = mn.vin.prevout.ToStringShort(); + std::string strTxHash = mn.vin.prevout.hash.ToString(); + uint32_t oIdx = mn.vin.prevout.n; + + if (strFilter != "" && strTxHash.find(strFilter) == std::string::npos && + mn.Status().find(strFilter) == std::string::npos && + EncodeDestination(mn.pubKeyCollateralAddress.GetID()).find(strFilter) == std::string::npos) continue; + + std::string strStatus = mn.Status(); + std::string strHost; + int port; + SplitHostPort(mn.addr.ToString(), port, strHost); + CNetAddr node; + LookupHost(strHost.c_str(), node, false); + std::string strNetwork = GetNetworkName(node.GetNetwork()); + + obj.pushKV("rank", (strStatus == "ENABLED" ? pos : 0)); + obj.pushKV("network", strNetwork); + obj.pushKV("txhash", strTxHash); + obj.pushKV("outidx", (uint64_t)oIdx); + obj.pushKV("pubkey", HexStr(mn.pubKeyMasternode)); + obj.pushKV("status", strStatus); + obj.pushKV("addr", EncodeDestination(mn.pubKeyCollateralAddress.GetID())); + obj.pushKV("version", mn.protocolVersion); + obj.pushKV("lastseen", (int64_t)mn.lastPing.sigTime); + obj.pushKV("activetime", (int64_t)(mn.lastPing.sigTime - mn.sigTime)); + obj.pushKV("lastpaid", (int64_t)mn.GetLastPaid()); - ret.push_back(obj); - } + ret.push_back(obj); } return ret;