From 7d14566bcd36a776f3e84846d2ffcf043b9b621a Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 16 Feb 2018 14:20:55 +0100 Subject: [PATCH] Add compatibility code to CMasternodeMan so that old code is still compatible ...when deterministic MNs are activated. --- src/masternode.cpp | 11 ++++ src/masternode.h | 3 ++ src/masternodeman.cpp | 116 +++++++++++++++++++++++++++++++----------- src/masternodeman.h | 2 +- 4 files changed, 101 insertions(+), 31 deletions(-) diff --git a/src/masternode.cpp b/src/masternode.cpp index 9c3686536..84a26ce6d 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -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(&dest)) + assert(false); // should not happen (previous verification forbids non p2pkh/p2pk + keyIDCollateralAddress = *boost::get(&dest); +} + // // When a new masternode broadcast is sent, update our information // diff --git a/src/masternode.h b/src/masternode.h index 09c634426..fdc94b58f 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -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; diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index fda6f89e0..3a1370da7 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -23,6 +23,7 @@ #include "warnings.h" #include "evo/deterministicmns.h" +#include "evo/providertx.h" /** Masternode manager */ CMasternodeMan mnodeman; @@ -389,20 +390,32 @@ void CMasternodeMan::Clear() int CMasternodeMan::CountMasternodes(int nProtocolVersion) { LOCK(cs); + int nCount = 0; nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion; - for (const auto& mnpair : mapMasternodes) { - if(mnpair.second.nProtocolVersion < nProtocolVersion) continue; - nCount++; + 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; @@ -464,43 +477,77 @@ void CMasternodeMan::DsegUpdate(CNode* pnode, CConnman& connman) CMasternode* CMasternodeMan::Find(const COutPoint &outpoint) { LOCK(cs); - auto it = mapMasternodes.find(outpoint); - return it == mapMasternodes.end() ? nullptr : &(it->second); + + 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); - for (const auto& mnpair : mapMasternodes) { - if (mnpair.second.keyIDOperator == keyIDOperator) { - mnInfoRet = mnpair.second.GetInfo(); - return true; + 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(); + return true; + } + } + return false; } - return false; } bool CMasternodeMan::GetMasternodeInfo(const CPubKey& pubKeyOperator, masternode_info_t& mnInfoRet) @@ -527,7 +574,11 @@ bool CMasternodeMan::GetMasternodeInfo(const CScript& payee, masternode_info_t& bool CMasternodeMan::Has(const COutPoint& outpoint) { LOCK(cs); - return mapMasternodes.find(outpoint) != mapMasternodes.end(); + if (deterministicMNManager->IsDeterministicMNsSporkActive()) { + return deterministicMNManager->HasValidMNAtChainTip(outpoint.hash); + } else { + return mapMasternodes.find(outpoint) != mapMasternodes.end(); + } } // @@ -1546,12 +1597,17 @@ std::string CMasternodeMan::ToString() const { std::ostringstream info; - 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; - + 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(); } @@ -1802,7 +1858,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; @@ -1813,11 +1869,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(); } diff --git a/src/masternodeman.h b/src/masternodeman.h index 2a3520060..e93200255 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -243,7 +243,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); };