From 96e0385db88b897311772ad26b594f3a33af45b3 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 13:15:13 +0100 Subject: [PATCH 01/26] Let "masternode winner/current" directly use deterministicMNManager --- src/rpc/masternode.cpp | 39 ++++++++++----------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 5e8281648d..87d8497648 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -270,29 +270,12 @@ UniValue masternode_count(const JSONRPCRequest& request) UniValue GetNextMasternodeForPayment(int heightShift) { - int nCount; - int nHeight; - masternode_info_t mnInfo; - CBlockIndex* pindex = NULL; - { - LOCK(cs_main); - pindex = chainActive.Tip(); - } - - nHeight = pindex->nHeight + heightShift; - mnodeman.UpdateLastPaid(pindex); - - CScript payeeScript; - if (deterministicMNManager->IsDIP3Active()) { - auto payee = deterministicMNManager->GetListAtChainTip().GetMNPayee(); - if (!payee || !mnodeman.GetMasternodeInfo(payee->proTxHash, mnInfo)) - return "unknown"; - payeeScript = payee->pdmnState->scriptPayout; - } else { - if (!mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount, mnInfo)) - return "unknown"; - payeeScript = GetScriptForDestination(mnInfo.keyIDCollateralAddress); - } + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto payees = mnList.GetProjectedMNPayees(heightShift); + if (payees.empty()) + return "unknown"; + auto payee = payees[heightShift - 9]; + CScript payeeScript = payee->pdmnState->scriptPayout; CTxDestination payeeDest; CBitcoinAddress payeeAddr; @@ -302,13 +285,11 @@ UniValue GetNextMasternodeForPayment(int heightShift) UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("height", nHeight)); - obj.push_back(Pair("IP:port", mnInfo.addr.ToString())); - obj.push_back(Pair("protocol", mnInfo.nProtocolVersion)); - obj.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort())); + obj.push_back(Pair("height", mnList.GetHeight() + heightShift)); + obj.push_back(Pair("IP:port", payee->pdmnState->addr.ToString())); + obj.push_back(Pair("proTxHash", payee->proTxHash.ToString())); + obj.push_back(Pair("outpoint", payee->collateralOutpoint.ToStringShort())); obj.push_back(Pair("payee", payeeAddr.IsValid() ? payeeAddr.ToString() : "UNKNOWN")); - obj.push_back(Pair("lastseen", mnInfo.nTimeLastPing)); - obj.push_back(Pair("activeseconds", mnInfo.nTimeLastPing - mnInfo.sigTime)); return obj; } From ae229e2833470020b983879de763a0a0265d00fd Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 13:34:52 +0100 Subject: [PATCH 02/26] Directly use deterministicMNManager in CGovernanceManager::GetCurrentVotes --- src/governance.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/governance.cpp b/src/governance.cpp index 496427a409..61be558a24 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -515,12 +515,17 @@ std::vector CGovernanceManager::GetCurrentVotes(const uint256& if (it == mapObjects.end()) return vecResult; const CGovernanceObject& govobj = it->second; - CMasternode mn; - std::map mapMasternodes; + auto mnList = deterministicMNManager->GetListAtChainTip(); + std::map mapMasternodes; if (mnCollateralOutpointFilter.IsNull()) { - mapMasternodes = mnodeman.GetFullMasternodeMap(); - } else if (mnodeman.Get(mnCollateralOutpointFilter, mn)) { - mapMasternodes[mnCollateralOutpointFilter] = mn; + mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) { + mapMasternodes.emplace(dmn->collateralOutpoint, dmn); + }); + } else { + auto dmn = mnList.GetValidMNByCollateral(mnCollateralOutpointFilter); + if (dmn) { + mapMasternodes.emplace(dmn->collateralOutpoint, dmn); + } } // Loop thru each MN collateral outpoint and get the votes for the `nParentHash` governance object From b49ef5d71217c33393be1fdab8e943dc0f107315 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 13:42:28 +0100 Subject: [PATCH 03/26] Directly use deterministicMNManager when processing DSTX --- src/masternodeman.cpp | 10 ++++++++++ src/masternodeman.h | 1 + src/net_processing.cpp | 9 ++++----- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 42bf3301b0..a6d4890164 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -127,6 +127,16 @@ void CMasternodeMan::AskForMN(CNode* pnode, const COutPoint& outpoint, CConnman& connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSEG, outpoint)); } +bool CMasternodeMan::IsValidForMixingTxes(const COutPoint& outpoint) +{ + LOCK(cs); + CMasternode* pmn = Find(outpoint); + if (!pmn) { + return false; + } + return pmn->IsValidForMixingTxes(); +} + bool CMasternodeMan::AllowMixing(const COutPoint &outpoint) { LOCK(cs); diff --git a/src/masternodeman.h b/src/masternodeman.h index 853fed8683..a2cb7c2c2b 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -137,6 +137,7 @@ public: void AskForMN(CNode *pnode, const COutPoint& outpoint, CConnman& connman); bool PoSeBan(const COutPoint &outpoint); + bool IsValidForMixingTxes(const COutPoint &outpoint); bool AllowMixing(const COutPoint &outpoint); bool DisallowMixing(const COutPoint &outpoint); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 699a3244dc..57e2d445a8 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2079,21 +2079,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; // not an error } - CMasternode mn; - - if(!mnodeman.Get(dstx.masternodeOutpoint, mn)) { + auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(dstx.masternodeOutpoint); + if(!dmn) { LogPrint("privatesend", "DSTX -- Can't find masternode %s to verify %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString()); return false; } - if(!mn.IsValidForMixingTxes()) { + if(!mnodeman.IsValidForMixingTxes(dstx.masternodeOutpoint)) { LogPrint("privatesend", "DSTX -- Masternode %s is sending too many transactions %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString()); return true; // TODO: Not an error? Could it be that someone is relaying old DSTXes // we have no idea about (e.g we were offline)? How to handle them? } - if (!dstx.CheckSignature(mn.legacyKeyIDOperator, mn.blsPubKeyOperator)) { + if (!dstx.CheckSignature(dmn->pdmnState->pubKeyOperator)) { LogPrint("privatesend", "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString()); return false; } From bc29fe160ebc9c5a4654d0b6da66cd66afd2e4dd Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 14:00:19 +0100 Subject: [PATCH 04/26] Remove compatibility code from governance RPCs and directly use deterministicMNManager --- src/rpc/governance.cpp | 201 +++++++++++++---------------------------- 1 file changed, 62 insertions(+), 139 deletions(-) diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index f6733db998..4a5b8db8db 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -412,10 +412,9 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request) UniValue statusObj(UniValue::VOBJ); UniValue returnObj(UniValue::VOBJ); - CMasternode mn; - bool fMnFound = mnodeman.Get(activeMasternodeInfo.outpoint, mn); + auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(activeMasternodeInfo.outpoint); - if (!fMnFound) { + if (!dmn) { nFailed++; statusObj.push_back(Pair("result", "failed")); statusObj.push_back(Pair("errorMessage", "Can't find masternode by collateral output")); @@ -425,19 +424,16 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request) return returnObj; } - CGovernanceVote vote(mn.outpoint, hash, eVoteSignal, eVoteOutcome); + CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome); bool signSuccess = false; - if (deterministicMNManager->IsDIP3Active()) { - if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals when deterministic masternodes are active"); - } - if (activeMasternodeInfo.blsKeyOperator) { - signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator); - } - } else { - signSuccess = vote.Sign(activeMasternodeInfo.legacyKeyOperator, activeMasternodeInfo.legacyKeyIDOperator); + if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && eVoteSignal == VOTE_SIGNAL_FUNDING) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Can't use vote-conf for proposals"); } + if (activeMasternodeInfo.blsKeyOperator) { + signSuccess = vote.Sign(*activeMasternodeInfo.blsKeyOperator); + } + if (!signSuccess) { nFailed++; statusObj.push_back(Pair("result", "failed")); @@ -466,9 +462,9 @@ UniValue gobject_vote_conf(const JSONRPCRequest& request) return returnObj; } -UniValue VoteWithMasternodeList(const std::vector& entries, - const uint256& hash, vote_signal_enum_t eVoteSignal, - vote_outcome_enum_t eVoteOutcome) +UniValue VoteWithMasternodes(const std::map& keys, + const uint256& hash, vote_signal_enum_t eVoteSignal, + vote_outcome_enum_t eVoteOutcome) { int govObjType; { @@ -483,59 +479,31 @@ UniValue VoteWithMasternodeList(const std::vectorGetListAtChainTip(); + UniValue resultsObj(UniValue::VOBJ); - for (const auto& mne : entries) { - CPubKey pubKeyOperator; - CKey keyOperator; + for (const auto& p : keys) { + const auto& proTxHash = p.first; + const auto& key = p.second; UniValue statusObj(UniValue::VOBJ); - if (!CMessageSigner::GetKeysFromSecret(mne.getPrivKey(), keyOperator, pubKeyOperator)) { + auto dmn = mnList.GetValidMN(proTxHash); + if (!dmn) { nFailed++; statusObj.push_back(Pair("result", "failed")); - statusObj.push_back(Pair("errorMessage", "Masternode signing error, could not set key correctly")); - resultsObj.push_back(Pair(mne.getAlias(), statusObj)); + statusObj.push_back(Pair("errorMessage", "Can't find masternode by proTxHash")); + resultsObj.push_back(Pair(proTxHash.ToString(), statusObj)); continue; } - uint256 nTxHash; - nTxHash.SetHex(mne.getTxHash()); - - int nOutputIndex = 0; - if (!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) { - continue; - } - - COutPoint outpoint(nTxHash, nOutputIndex); - - CMasternode mn; - bool fMnFound = mnodeman.Get(outpoint, mn); - - if (!fMnFound) { - nFailed++; - statusObj.push_back(Pair("result", "failed")); - statusObj.push_back(Pair("errorMessage", "Can't find masternode by collateral output")); - resultsObj.push_back(Pair(mne.getAlias(), statusObj)); - continue; - } - - if (deterministicMNManager->IsDIP3Active()) { - if (govObjType == GOVERNANCE_OBJECT_PROPOSAL && mn.keyIDVoting != pubKeyOperator.GetID()) { - nFailed++; - statusObj.push_back(Pair("result", "failed")); - statusObj.push_back(Pair("errorMessage", "Can't vote on proposal when key does not match voting key")); - resultsObj.push_back(Pair(mne.getAlias(), statusObj)); - continue; - } - } - - CGovernanceVote vote(mn.outpoint, hash, eVoteSignal, eVoteOutcome); - if (!vote.Sign(keyOperator, pubKeyOperator.GetID())) { + CGovernanceVote vote(dmn->collateralOutpoint, hash, eVoteSignal, eVoteOutcome); + if (!vote.Sign(key, key.GetPubKey().GetID())) { nFailed++; statusObj.push_back(Pair("result", "failed")); statusObj.push_back(Pair("errorMessage", "Failure to sign.")); - resultsObj.push_back(Pair(mne.getAlias(), statusObj)); + resultsObj.push_back(Pair(proTxHash.ToString(), statusObj)); continue; } @@ -549,7 +517,7 @@ UniValue VoteWithMasternodeList(const std::vector \n" - "Vote on a governance object by all masternodes (using masternode.conf setup)\n" + "Vote on a governance object by all masternodes for which the voting key is present in the local wallet\n" "\nArguments:\n" "1. governance-hash (string, required) hash of the governance object\n" "2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n" @@ -592,66 +561,33 @@ UniValue gobject_vote_many(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'"); } - std::vector entries = masternodeConfig.getEntries(); - -#ifdef ENABLE_WALLET - // This is a hack to maintain code-level backwards compatibility with masternode.conf and the deterministic masternodes. - // Deterministic masternode keys are managed inside the wallet instead of masternode.conf - // This allows voting on proposals when you have the MN voting key in your wallet - // We can remove this when we remove support for masternode.conf and only support wallet based masternode - // management - if (deterministicMNManager->IsDIP3Active()) { - if (!pwalletMain) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled."); - } - entries.clear(); - - auto mnList = deterministicMNManager->GetListAtChainTip(); - mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) { - bool found = false; - for (const auto &mne : entries) { - uint256 nTxHash; - nTxHash.SetHex(mne.getTxHash()); - - int nOutputIndex = 0; - if(!ParseInt32(mne.getOutputIndex(), &nOutputIndex)) { - continue; - } - - if (nTxHash == dmn->collateralOutpoint.hash && (uint32_t)nOutputIndex == dmn->collateralOutpoint.n) { - found = true; - break; - } - } - if (!found) { - CKey ownerKey; - if (pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, ownerKey)) { - CBitcoinSecret secret(ownerKey); - CMasternodeConfig::CMasternodeEntry mne(dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort(false), secret.ToString(), dmn->collateralOutpoint.hash.ToString(), itostr(dmn->collateralOutpoint.n)); - entries.push_back(mne); - } - } - }); - } -#else - if (deterministicMNManager->IsDIP3Active()) { + if (!pwalletMain) { throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled."); } -#endif - return VoteWithMasternodeList(entries, hash, eVoteSignal, eVoteOutcome); + std::map votingKeys; + + auto mnList = deterministicMNManager->GetListAtChainTip(); + mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) { + CKey votingKey; + if (pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) { + votingKeys.emplace(dmn->proTxHash, votingKey); + } + }); + + return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome); } void gobject_vote_alias_help() { throw std::runtime_error( "gobject vote-alias \n" - "Vote on a governance object by masternode alias (using masternode.conf setup)\n" + "Vote on a governance object by masternode's voting key (if present in local wallet)\n" "\nArguments:\n" "1. governance-hash (string, required) hash of the governance object\n" "2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n" "3. vote-outcome (string, required) vote outcome, possible values: [yes|no|abstain]\n" - "4. alias-name (string, required) masternode alias or proTxHash after DIP3 activation" + "4. protx-hash (string, required) masternode's proTxHash" ); } @@ -676,41 +612,27 @@ UniValue gobject_vote_alias(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'"); } - std::vector entries; - - if (deterministicMNManager->IsDIP3Active()) { -#ifdef ENABLE_WALLET - if (!pwalletMain) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled"); - } - - uint256 proTxHash = ParseHashV(request.params[4], "alias-name"); - auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash); - if (!dmn) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash"); - } - - CKey votingKey; - if (!pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Voting ekey %s not known by wallet", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString())); - } - - CBitcoinSecret secret(votingKey); - CMasternodeConfig::CMasternodeEntry mne(dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToStringIPPort(false), secret.ToString(), dmn->collateralOutpoint.hash.ToString(), itostr(dmn->collateralOutpoint.n)); - entries.push_back(mne); -#else + if (!pwalletMain) { throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled"); -#endif - } else { - std::string strAlias = request.params[4].get_str(); - for (const auto& mne : masternodeConfig.getEntries()) { - if (strAlias == mne.getAlias()) - entries.push_back(mne); - } } - return VoteWithMasternodeList(entries, hash, eVoteSignal, eVoteOutcome); + uint256 proTxHash = ParseHashV(request.params[4], "protx-hash"); + auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash); + if (!dmn) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash"); + } + + CKey votingKey; + if (!pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Voting key %s not known by wallet", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString())); + } + + std::map votingKeys; + votingKeys.emplace(proTxHash, votingKey); + + return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome); } +#endif UniValue ListObjects(const std::string& strCachedSignal, const std::string& strType, int nStartTime) { @@ -1063,10 +985,12 @@ UniValue gobject(const JSONRPCRequest& request) return gobject_submit(request); } else if (strCommand == "vote-conf") { return gobject_vote_conf(request); +#ifdef ENABLE_WALLET } else if (strCommand == "vote-many") { return gobject_vote_many(request); } else if (strCommand == "vote-alias") { return gobject_vote_alias(request); +#endif } else if (strCommand == "list") { // USERS CAN QUERY THE SYSTEM FOR A LIST OF VARIOUS GOVERNANCE ITEMS return gobject_list(request); @@ -1133,10 +1057,9 @@ UniValue voteraw(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); } - CMasternode mn; - bool fMnFound = mnodeman.Get(outpoint, mn); + auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(outpoint); - if (!fMnFound) { + if (!dmn) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Failure to find masternode in list : " + outpoint.ToStringShort()); } From 45f34e130f91cf139f376046b81e019929160894 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 14:24:48 +0100 Subject: [PATCH 05/26] Implement HasValidMN, HasValidMNByCollateral and GetValidMNByCollateral --- src/evo/deterministicmns.cpp | 23 +++++++++-------------- src/evo/deterministicmns.h | 17 +++++++++++++---- src/masternodeman.cpp | 2 +- src/wallet/wallet.cpp | 11 ++++++++--- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 8f1140fd97..0f79db6667 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -151,6 +151,15 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNByCollateral(const COutPoint& co return GetUniquePropertyMN(collateralOutpoint); } +CDeterministicMNCPtr CDeterministicMNList::GetValidMNByCollateral(const COutPoint& collateralOutpoint) const +{ + auto dmn = GetMNByCollateral(collateralOutpoint); + if (dmn && !IsMNValid(dmn)) { + return nullptr; + } + return dmn; +} + static int CompareByLastPaid_GetHeight(const CDeterministicMN& dmn) { int height = dmn.pdmnState->nLastPaidHeight; @@ -826,20 +835,6 @@ CDeterministicMNList CDeterministicMNManager::GetListAtChainTip() return GetListForBlock(tipBlockHash); } -bool CDeterministicMNManager::HasValidMNCollateralAtChainTip(const COutPoint& outpoint) -{ - auto mnList = GetListAtChainTip(); - auto dmn = mnList.GetMNByCollateral(outpoint); - return dmn && mnList.IsMNValid(dmn); -} - -bool CDeterministicMNManager::HasMNCollateralAtChainTip(const COutPoint& outpoint) -{ - auto mnList = GetListAtChainTip(); - auto dmn = mnList.GetMNByCollateral(outpoint); - return dmn != nullptr; -} - bool CDeterministicMNManager::IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n) { if (tx->nVersion != 3 || tx->nType != TRANSACTION_PROVIDER_REGISTER) { diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 48729c0b92..6a8469b117 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -289,10 +289,23 @@ public: { return GetMN(proTxHash) != nullptr; } + bool HasValidMN(const uint256& proTxHash) const + { + return GetValidMN(proTxHash) != nullptr; + } + bool HasMNByCollateral(const COutPoint& collateralOutpoint) const + { + return GetMNByCollateral(collateralOutpoint) != nullptr; + } + bool HasValidMNByCollateral(const COutPoint& collateralOutpoint) const + { + return GetValidMNByCollateral(collateralOutpoint) != nullptr; + } CDeterministicMNCPtr GetMN(const uint256& proTxHash) const; CDeterministicMNCPtr GetValidMN(const uint256& proTxHash) const; CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey& pubKey); CDeterministicMNCPtr GetMNByCollateral(const COutPoint& collateralOutpoint) const; + CDeterministicMNCPtr GetValidMNByCollateral(const COutPoint& collateralOutpoint) const; CDeterministicMNCPtr GetMNPayee() const; /** @@ -479,10 +492,6 @@ public: CDeterministicMNList GetListForBlock(const uint256& blockHash); CDeterministicMNList GetListAtChainTip(); - // TODO remove after removal of old non-deterministic lists - bool HasValidMNCollateralAtChainTip(const COutPoint& outpoint); - bool HasMNCollateralAtChainTip(const COutPoint& outpoint); - // Test if given TX is a ProRegTx which also contains the collateral at index n bool IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n); diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index a6d4890164..9fb09bae51 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -643,7 +643,7 @@ bool CMasternodeMan::Has(const COutPoint& outpoint) { LOCK(cs); if (deterministicMNManager->IsDIP3Active()) { - return deterministicMNManager->HasValidMNCollateralAtChainTip(outpoint); + return deterministicMNManager->GetListAtChainTip().HasValidMNByCollateral(outpoint); } else { return mapMasternodes.find(outpoint) != mapMasternodes.end(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 553a912d7b..d0982ba94a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1121,10 +1121,11 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) } AddToSpends(hash); + auto mnList = deterministicMNManager->GetListAtChainTip(); for(unsigned int i = 0; i < wtx.tx->vout.size(); ++i) { if (IsMine(wtx.tx->vout[i]) && !IsSpent(hash, i)) { setWalletUTXO.insert(COutPoint(hash, i)); - if (deterministicMNManager->IsProTxWithCollateral(wtx.tx, i) || deterministicMNManager->HasMNCollateralAtChainTip(COutPoint(hash, i))) { + if (deterministicMNManager->IsProTxWithCollateral(wtx.tx, i) || mnList.HasMNByCollateral(COutPoint(hash, i))) { LockCoin(COutPoint(hash, i)); } } @@ -3989,11 +3990,13 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) // This avoids accidential spending of collaterals. They can still be unlocked manually if a spend is really intended. void CWallet::AutoLockMasternodeCollaterals() { + auto mnList = deterministicMNManager->GetListAtChainTip(); + LOCK2(cs_main, cs_wallet); for (const auto& pair : mapWallet) { for (unsigned int i = 0; i < pair.second.tx->vout.size(); ++i) { if (IsMine(pair.second.tx->vout[i]) && !IsSpent(pair.first, i)) { - if (deterministicMNManager->IsProTxWithCollateral(pair.second.tx, i) || deterministicMNManager->HasMNCollateralAtChainTip(COutPoint(pair.first, i))) { + if (deterministicMNManager->IsProTxWithCollateral(pair.second.tx, i) || mnList.HasMNByCollateral(COutPoint(pair.first, i))) { LockCoin(COutPoint(pair.first, i)); } } @@ -4643,11 +4646,13 @@ void CWallet::ListLockedCoins(std::vector& vOutpts) void CWallet::ListProTxCoins(std::vector& vOutpts) { + auto mnList = deterministicMNManager->GetListAtChainTip(); + AssertLockHeld(cs_wallet); for (const auto &o : setWalletUTXO) { if (mapWallet.count(o.hash)) { const auto &p = mapWallet[o.hash]; - if (deterministicMNManager->IsProTxWithCollateral(p.tx, o.n) || deterministicMNManager->HasMNCollateralAtChainTip(o)) { + if (deterministicMNManager->IsProTxWithCollateral(p.tx, o.n) || mnList.HasMNByCollateral(o)) { vOutpts.emplace_back(o); } } From 1ff241881fd1b418a3f32f83433b75bbf33e1f76 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 14:34:50 +0100 Subject: [PATCH 06/26] Directly use deterministicMNManager in some places --- src/governance-object.cpp | 11 ++++++++--- src/instantx.cpp | 4 +++- src/rpc/governance.cpp | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/governance-object.cpp b/src/governance-object.cpp index 5eaba3c54e..4ea1bc5afd 100644 --- a/src/governance-object.cpp +++ b/src/governance-object.cpp @@ -116,7 +116,9 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, return false; } - if (!mnodeman.Has(vote.GetMasternodeOutpoint())) { + auto mnList = deterministicMNManager->GetListAtChainTip(); + + if (!mnList.HasValidMNByCollateral(vote.GetMasternodeOutpoint())) { std::ostringstream ostr; ostr << "CGovernanceObject::ProcessVote -- Masternode " << vote.GetMasternodeOutpoint().ToStringShort() << " not found"; exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_WARNING); @@ -212,9 +214,11 @@ void CGovernanceObject::ClearMasternodeVotes() { LOCK(cs); + auto mnList = deterministicMNManager->GetListAtChainTip(); + vote_m_it it = mapCurrentMNVotes.begin(); while (it != mapCurrentMNVotes.end()) { - if (!mnodeman.Has(it->first)) { + if (!mnList.HasValidMNByCollateral(it->first)) { fileVotes.RemoveVotesFromMasternode(it->first); mapCurrentMNVotes.erase(it++); } else { @@ -812,6 +816,7 @@ void CGovernanceObject::UpdateSentinelVariables() void CGovernanceObject::CheckOrphanVotes(CConnman& connman) { int64_t nNow = GetAdjustedTime(); + auto mnList = deterministicMNManager->GetListAtChainTip(); const vote_cmm_t::list_t& listVotes = cmmapOrphanVotes.GetItemList(); vote_cmm_t::list_cit it = listVotes.begin(); while (it != listVotes.end()) { @@ -821,7 +826,7 @@ void CGovernanceObject::CheckOrphanVotes(CConnman& connman) const CGovernanceVote& vote = pairVote.first; if (pairVote.second < nNow) { fRemove = true; - } else if (!mnodeman.Has(vote.GetMasternodeOutpoint())) { + } else if (!mnList.HasValidMNByCollateral(vote.GetMasternodeOutpoint())) { ++it; continue; } diff --git a/src/instantx.cpp b/src/instantx.cpp index db2e2cc0ea..d97f163a20 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -1029,7 +1029,9 @@ bool CTxLockRequest::IsSimple() const bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const { - if (!mnodeman.Has(outpointMasternode)) { + auto mnList = deterministicMNManager->GetListAtChainTip(); + + if (!mnList.HasValidMNByCollateral(outpointMasternode)) { LogPrint("instantsend", "CTxLockVote::IsValid -- Unknown masternode %s\n", outpointMasternode.ToStringShort()); mnodeman.AskForMN(pnode, outpointMasternode, connman); return false; diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 4a5b8db8db..16ad1c891d 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -261,7 +261,8 @@ UniValue gobject_submit(const JSONRPCRequest& request) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Must wait for client to sync with masternode network. Try again in a minute or so."); } - bool fMnFound = mnodeman.Has(activeMasternodeInfo.outpoint); + auto mnList = deterministicMNManager->GetListAtChainTip(); + bool fMnFound = mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint); DBG( std::cout << "gobject: submit activeMasternodeInfo.keyIDOperator = " << activeMasternodeInfo.legacyKeyIDOperator.ToString() << ", outpoint = " << activeMasternodeInfo.outpoint.ToStringShort() From 14d8ce03c0bb9371231656596fb88e2f5250de90 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 14:42:48 +0100 Subject: [PATCH 07/26] Don't use GetMasternodeInfo in CTxLockVote::IsValid --- src/instantx.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index d97f163a20..60a2d8b443 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -1038,15 +1038,16 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const } // Verify that masternodeProTxHash belongs to the same MN referred by the collateral - // Only v13 nodes will send us locks with this field set, and only after spork15 activation + // This is a leftover from the legacy non-deterministic MN list where we used the collateral to identify MNs + // TODO eventually remove the collateral from CTxLockVote if (!masternodeProTxHash.IsNull()) { - masternode_info_t mnInfo; - if (!mnodeman.GetMasternodeInfo(masternodeProTxHash, mnInfo) || mnInfo.outpoint != outpointMasternode) { + auto dmn = mnList.GetValidMN(masternodeProTxHash); + if (!dmn || dmn->collateralOutpoint != outpointMasternode) { LogPrint("instantsend", "CTxLockVote::IsValid -- invalid masternodeProTxHash %s\n", masternodeProTxHash.ToString()); return false; } - } else if (deterministicMNManager->IsDIP3Active()) { - LogPrint("instantsend", "CTxLockVote::IsValid -- missing masternodeProTxHash while DIP3 is active\n"); + } else { + LogPrint("instantsend", "CTxLockVote::IsValid -- missing masternodeProTxHash\n"); return false; } From 2b2e4f45da100872f7ea46bf00d7dce7b495efb9 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 15:39:21 +0100 Subject: [PATCH 08/26] Remove a few uses of mnodeman from governance code And remove them with direct use of deterministicMNManager --- src/governance-object.cpp | 24 ++++++++---------------- src/governance-vote.cpp | 12 ++++-------- src/governance.cpp | 2 +- 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/governance-object.cpp b/src/governance-object.cpp index 4ea1bc5afd..d8694ee20e 100644 --- a/src/governance-object.cpp +++ b/src/governance-object.cpp @@ -123,9 +123,6 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, ostr << "CGovernanceObject::ProcessVote -- Masternode " << vote.GetMasternodeOutpoint().ToStringShort() << " not found"; exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_WARNING); if (cmmapOrphanVotes.Insert(vote.GetMasternodeOutpoint(), vote_time_pair_t(vote, GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME))) { - if (pfrom) { - mnodeman.AskForMN(pfrom, vote.GetMasternodeOutpoint(), connman); - } LogPrintf("%s\n", ostr.str()); } else { LogPrint("gobject", "%s\n", ostr.str()); @@ -556,9 +553,11 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast return true; } + auto mnList = deterministicMNManager->GetListAtChainTip(); + std::string strOutpoint = masternodeOutpoint.ToStringShort(); - masternode_info_t infoMn; - if (!mnodeman.GetMasternodeInfo(masternodeOutpoint, infoMn)) { + auto dmn = mnList.GetValidMNByCollateral(masternodeOutpoint); + if (!dmn) { CMasternode::CollateralStatus err = CMasternode::CheckCollateral(masternodeOutpoint, CKeyID()); if (err == CMasternode::COLLATERAL_UTXO_NOT_FOUND) { strError = "Failed to find Masternode UTXO, missing masternode=" + strOutpoint + "\n"; @@ -576,16 +575,9 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast } // Check that we have a valid MN signature - if (deterministicMNManager->IsDIP3Active()) { - if (!CheckSignature(infoMn.blsPubKeyOperator)) { - strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.blsPubKeyOperator.ToString(); - return false; - } - } else { - if (!CheckSignature(infoMn.legacyKeyIDOperator)) { - strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey id = " + infoMn.legacyKeyIDOperator.ToString(); - return false; - } + if (!CheckSignature(dmn->pdmnState->pubKeyOperator)) { + strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey = " + dmn->pdmnState->pubKeyOperator.ToString(); + return false; } return true; @@ -783,7 +775,7 @@ void CGovernanceObject::UpdateSentinelVariables() { // CALCULATE MINIMUM SUPPORT LEVELS REQUIRED - int nMnCount = mnodeman.CountEnabled(); + int nMnCount = (int)deterministicMNManager->GetListAtChainTip().GetValidMNsCount(); if (nMnCount == 0) return; // CALCULATE THE MINUMUM VOTE COUNT REQUIRED FOR FULL SIGNAL diff --git a/src/governance-vote.cpp b/src/governance-vote.cpp index 64ea647973..2b80cf8367 100644 --- a/src/governance-vote.cpp +++ b/src/governance-vote.cpp @@ -256,20 +256,16 @@ bool CGovernanceVote::IsValid(bool useVotingKey) const return false; } - masternode_info_t infoMn; - if (!mnodeman.GetMasternodeInfo(masternodeOutpoint, infoMn)) { + auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(masternodeOutpoint); + if (!dmn) { LogPrint("gobject", "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort()); return false; } if (useVotingKey) { - return CheckSignature(infoMn.keyIDVoting); + return CheckSignature(dmn->pdmnState->keyIDVoting); } else { - if (deterministicMNManager->IsDIP3Active()) { - return CheckSignature(infoMn.blsPubKeyOperator); - } else { - return CheckSignature(infoMn.legacyKeyIDOperator); - } + return CheckSignature(dmn->pdmnState->pubKeyOperator); } } diff --git a/src/governance.cpp b/src/governance.cpp index 61be558a24..665f37debb 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -1079,7 +1079,7 @@ int CGovernanceManager::RequestGovernanceObjectVotes(const std::vector& int nMaxObjRequestsPerNode = 1; size_t nProjectedVotes = 2000; if (Params().NetworkIDString() != CBaseChainParams::MAIN) { - nMaxObjRequestsPerNode = std::max(1, int(nProjectedVotes / std::max(1, mnodeman.size()))); + nMaxObjRequestsPerNode = std::max(1, int(nProjectedVotes / std::max(1, (int)deterministicMNManager->GetListAtChainTip().GetValidMNsCount()))); } { From da924519a49d05b8da79285cd90618b24d8364a6 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 14:51:59 +0100 Subject: [PATCH 09/26] Remove support for legacy signatures in CTxLockVote --- src/instantx.cpp | 70 ++++++++---------------------------------------- 1 file changed, 11 insertions(+), 59 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index 60a2d8b443..2a35f08ad7 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -1115,35 +1115,14 @@ bool CTxLockVote::CheckSignature() const return false; } - if (deterministicMNManager->IsDIP3Active()) { - uint256 hash = GetSignatureHash(); + uint256 hash = GetSignatureHash(); - CBLSSignature sig; - sig.SetBuf(vchMasternodeSignature); - if (!sig.IsValid() || !sig.VerifyInsecure(infoMn.blsPubKeyOperator, hash)) { - LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); - return false; - } - } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) { - uint256 hash = GetSignatureHash(); - - if (!CHashSigner::VerifyHash(hash, infoMn.legacyKeyIDOperator, vchMasternodeSignature, strError)) { - // could be a signature in old format - std::string strMessage = txHash.ToString() + outpoint.ToStringShort(); - if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) { - // nope, not in old format either - LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError); - return false; - } - } - } else { - std::string strMessage = txHash.ToString() + outpoint.ToStringShort(); - if (!CMessageSigner::VerifyMessage(infoMn.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) { - LogPrintf("CTxLockVote::CheckSignature -- VerifyMessage() failed, error: %s\n", strError); - return false; - } + CBLSSignature sig; + sig.SetBuf(vchMasternodeSignature); + if (!sig.IsValid() || !sig.VerifyInsecure(infoMn.blsPubKeyOperator, hash)) { + LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); + return false; } - return true; } @@ -1151,40 +1130,13 @@ bool CTxLockVote::Sign() { std::string strError; - if (deterministicMNManager->IsDIP3Active()) { - uint256 hash = GetSignatureHash(); + uint256 hash = GetSignatureHash(); - CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); - if (!sig.IsValid()) { - return false; - } - sig.GetBuf(vchMasternodeSignature); - } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) { - uint256 hash = GetSignatureHash(); - - if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchMasternodeSignature)) { - LogPrintf("CTxLockVote::Sign -- SignHash() failed\n"); - return false; - } - - if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strError)) { - LogPrintf("CTxLockVote::Sign -- VerifyHash() failed, error: %s\n", strError); - return false; - } - } else { - std::string strMessage = txHash.ToString() + outpoint.ToStringShort(); - - if (!CMessageSigner::SignMessage(strMessage, vchMasternodeSignature, activeMasternodeInfo.legacyKeyOperator)) { - LogPrintf("CTxLockVote::Sign -- SignMessage() failed\n"); - return false; - } - - if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchMasternodeSignature, strMessage, strError)) { - LogPrintf("CTxLockVote::Sign -- VerifyMessage() failed, error: %s\n", strError); - return false; - } + CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); + if (!sig.IsValid()) { + return false; } - + sig.GetBuf(vchMasternodeSignature); return true; } From 5f5fcc49cd4e95aad3c5ed2b87cdc4dc1ec9bf1e Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 15:00:10 +0100 Subject: [PATCH 10/26] Remove legacy signatures support in CPrivateSendQueue --- src/privatesend.cpp | 73 ++++++++------------------------------------- src/privatesend.h | 2 +- 2 files changed, 13 insertions(+), 62 deletions(-) diff --git a/src/privatesend.cpp b/src/privatesend.cpp index 01db2b1cc6..b821533a22 100644 --- a/src/privatesend.cpp +++ b/src/privatesend.cpp @@ -52,75 +52,26 @@ bool CPrivateSendQueue::Sign() std::string strError = ""; - if (deterministicMNManager->IsDIP3Active()) { - uint256 hash = GetSignatureHash(); - CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); - if (!sig.IsValid()) { - return false; - } - sig.GetBuf(vchSig); - } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) { - uint256 hash = GetSignatureHash(); - - if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) { - LogPrintf("CPrivateSendQueue::Sign -- SignHash() failed\n"); - return false; - } - - if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) { - LogPrintf("CPrivateSendQueue::Sign -- VerifyHash() failed, error: %s\n", strError); - return false; - } - } else { - std::string strMessage = CTxIn(masternodeOutpoint).ToString() + - std::to_string(nDenom) + - std::to_string(nTime) + - std::to_string(fReady); - - if (!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) { - LogPrintf("CPrivateSendQueue::Sign -- SignMessage() failed, %s\n", ToString()); - return false; - } - - if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) { - LogPrintf("CPrivateSendQueue::Sign -- VerifyMessage() failed, error: %s\n", strError); - return false; - } + uint256 hash = GetSignatureHash(); + CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); + if (!sig.IsValid()) { + return false; } + sig.GetBuf(vchSig); return true; } -bool CPrivateSendQueue::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const +bool CPrivateSendQueue::CheckSignature(const CBLSPublicKey& blsPubKey) const { std::string strError = ""; - if (deterministicMNManager->IsDIP3Active()) { - uint256 hash = GetSignatureHash(); + uint256 hash = GetSignatureHash(); - CBLSSignature sig; - sig.SetBuf(vchSig); - if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) { - LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); - return false; - } - } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) { - uint256 hash = GetSignatureHash(); - - if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) { - // we don't care about queues with old signature format - LogPrintf("CPrivateSendQueue::CheckSignature -- VerifyHash() failed, error: %s\n", strError); - return false; - } - } else { - std::string strMessage = CTxIn(masternodeOutpoint).ToString() + - std::to_string(nDenom) + - std::to_string(nTime) + - std::to_string(fReady); - - if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) { - LogPrintf("CPrivateSendQueue::CheckSignature -- Got bad Masternode queue signature: %s; error: %s\n", ToString(), strError); - return false; - } + CBLSSignature sig; + sig.SetBuf(vchSig); + if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) { + LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); + return false; } return true; diff --git a/src/privatesend.h b/src/privatesend.h index 440da1e7a0..a88171444c 100644 --- a/src/privatesend.h +++ b/src/privatesend.h @@ -225,7 +225,7 @@ public: */ bool Sign(); /// Check if we have a valid Masternode address - bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const; + bool CheckSignature(const CBLSPublicKey& blsPubKey) const; bool Relay(CConnman& connman); From fb13b000b5959f54f3b33ca6953e201006403a89 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 13:40:29 +0100 Subject: [PATCH 11/26] Remove support for legacy operator keys in CPrivateSendBroadcastTx --- src/privatesend.cpp | 67 ++++++++------------------------------------- src/privatesend.h | 2 +- 2 files changed, 13 insertions(+), 56 deletions(-) diff --git a/src/privatesend.cpp b/src/privatesend.cpp index b821533a22..2f7e6f1222 100644 --- a/src/privatesend.cpp +++ b/src/privatesend.cpp @@ -98,71 +98,28 @@ bool CPrivateSendBroadcastTx::Sign() std::string strError = ""; - if (deterministicMNManager->IsDIP3Active()) { - uint256 hash = GetSignatureHash(); + uint256 hash = GetSignatureHash(); - CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); - if (!sig.IsValid()) { - return false; - } - sig.GetBuf(vchSig); - } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) { - uint256 hash = GetSignatureHash(); - - if (!CHashSigner::SignHash(hash, activeMasternodeInfo.legacyKeyOperator, vchSig)) { - LogPrintf("CPrivateSendBroadcastTx::Sign -- SignHash() failed\n"); - return false; - } - - if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.legacyKeyIDOperator, vchSig, strError)) { - LogPrintf("CPrivateSendBroadcastTx::Sign -- VerifyHash() failed, error: %s\n", strError); - return false; - } - } else { - std::string strMessage = tx->GetHash().ToString() + std::to_string(sigTime); - - if (!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.legacyKeyOperator)) { - LogPrintf("CPrivateSendBroadcastTx::Sign -- SignMessage() failed\n"); - return false; - } - - if (!CMessageSigner::VerifyMessage(activeMasternodeInfo.legacyKeyIDOperator, vchSig, strMessage, strError)) { - LogPrintf("CPrivateSendBroadcastTx::Sign -- VerifyMessage() failed, error: %s\n", strError); - return false; - } + CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); + if (!sig.IsValid()) { + return false; } + sig.GetBuf(vchSig); return true; } -bool CPrivateSendBroadcastTx::CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const +bool CPrivateSendBroadcastTx::CheckSignature(const CBLSPublicKey& blsPubKey) const { std::string strError = ""; - if (deterministicMNManager->IsDIP3Active()) { - uint256 hash = GetSignatureHash(); + uint256 hash = GetSignatureHash(); - CBLSSignature sig; - sig.SetBuf(vchSig); - if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) { - LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); - return false; - } - } else if (sporkManager.IsSporkActive(SPORK_6_NEW_SIGS)) { - uint256 hash = GetSignatureHash(); - - if (!CHashSigner::VerifyHash(hash, keyIDOperator, vchSig, strError)) { - // we don't care about dstxes with old signature format - LogPrintf("CPrivateSendBroadcastTx::CheckSignature -- VerifyHash() failed, error: %s\n", strError); - return false; - } - } else { - std::string strMessage = tx->GetHash().ToString() + std::to_string(sigTime); - - if (!CMessageSigner::VerifyMessage(keyIDOperator, vchSig, strMessage, strError)) { - LogPrintf("CPrivateSendBroadcastTx::CheckSignature -- Got bad dstx signature, error: %s\n", strError); - return false; - } + CBLSSignature sig; + sig.SetBuf(vchSig); + if (!sig.IsValid() || !sig.VerifyInsecure(blsPubKey, hash)) { + LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); + return false; } return true; diff --git a/src/privatesend.h b/src/privatesend.h index a88171444c..f8e85097e3 100644 --- a/src/privatesend.h +++ b/src/privatesend.h @@ -306,7 +306,7 @@ public: uint256 GetSignatureHash() const; bool Sign(); - bool CheckSignature(const CKeyID& keyIDOperator, const CBLSPublicKey& blsPubKey) const; + bool CheckSignature(const CBLSPublicKey& blsPubKey) const; void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; } bool IsExpired(int nHeight); From eedb158459ac201c5373e79ed27bafcaf8f4632f Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 15:41:24 +0100 Subject: [PATCH 12/26] Remove use of mnodeman.GetMasternodeInfo from IX code --- src/instantx.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index 2a35f08ad7..b598bc8713 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -1108,10 +1108,9 @@ bool CTxLockVote::CheckSignature() const { std::string strError; - masternode_info_t infoMn; - - if (!mnodeman.GetMasternodeInfo(outpointMasternode, infoMn)) { - LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", outpointMasternode.ToString()); + auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(masternodeProTxHash); + if (!dmn) { + LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", masternodeProTxHash.ToString()); return false; } @@ -1119,7 +1118,7 @@ bool CTxLockVote::CheckSignature() const CBLSSignature sig; sig.SetBuf(vchMasternodeSignature); - if (!sig.IsValid() || !sig.VerifyInsecure(infoMn.blsPubKeyOperator, hash)) { + if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator, hash)) { LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); return false; } From 2f66d6ada12f53f4b596e746887e3000d7efe6aa Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 15:45:36 +0100 Subject: [PATCH 13/26] Replace uses of mnodeman in PS code when deterministicMNManager can be used directly Additionally, implement GetLastDsq in CMasternodeMan as a replacement for direct access to the masternode_info_t object. Will move this variable to another (PS specific) place later. --- src/masternode-payments.cpp | 4 +- src/masternode-payments.h | 2 +- src/masternodeman.cpp | 20 ++++-- src/masternodeman.h | 1 + src/privatesend-client.cpp | 132 ++++++++++++++++++------------------ src/privatesend-client.h | 11 +-- src/privatesend-server.cpp | 31 +++++---- src/rpc/masternode.cpp | 10 +-- 8 files changed, 115 insertions(+), 96 deletions(-) diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index aca4b632b4..99a647178c 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -641,14 +641,14 @@ bool CMasternodePayments::GetBlockTxOuts(int nBlockHeight, CAmount blockReward, // Is this masternode scheduled to get paid soon? // -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 blocks of votes -bool CMasternodePayments::IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const +bool CMasternodePayments::IsScheduled(const CDeterministicMNCPtr& dmnIn, int nNotBlockHeight) const { LOCK(cs_mapMasternodeBlocks); if (deterministicMNManager->IsDIP3Active()) { auto projectedPayees = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(8); for (const auto &dmn : projectedPayees) { - if (dmn->collateralOutpoint == mnInfo.outpoint) { + if (dmn->proTxHash == dmnIn->proTxHash) { return true; } } diff --git a/src/masternode-payments.h b/src/masternode-payments.h index 984551c923..9a41dae0c3 100644 --- a/src/masternode-payments.h +++ b/src/masternode-payments.h @@ -200,7 +200,7 @@ public: bool GetBlockTxOuts(int nBlockHeight, CAmount blockReward, std::vector& voutMasternodePaymentsRet) const; bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const; - bool IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const; + bool IsScheduled(const CDeterministicMNCPtr& dmn, int nNotBlockHeight) const; bool UpdateLastVote(const CMasternodePaymentVote& vote); diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 9fb09bae51..88b86a9247 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -163,6 +163,16 @@ bool CMasternodeMan::DisallowMixing(const COutPoint &outpoint) return true; } +int64_t CMasternodeMan::GetLastDsq(const COutPoint& outpoint) +{ + LOCK(cs); + CMasternode* pmn = Find(outpoint); + if (!pmn) { + return 0; + } + return pmn->nLastDsq; +} + bool CMasternodeMan::PoSeBan(const COutPoint &outpoint) { LOCK(cs); @@ -901,17 +911,17 @@ bool CMasternodeMan::GetMasternodeRanks(CMasternodeMan::rank_pair_vec_t& vecMast void CMasternodeMan::ProcessMasternodeConnections(CConnman& connman) { - std::vector vecMnInfo; // will be empty when no wallet + std::vector vecDmns; // will be empty when no wallet #ifdef ENABLE_WALLET - privateSendClient.GetMixingMasternodesInfo(vecMnInfo); + privateSendClient.GetMixingMasternodesInfo(vecDmns); #endif // ENABLE_WALLET - connman.ForEachNode(CConnman::AllNodes, [&vecMnInfo](CNode* pnode) { + connman.ForEachNode(CConnman::AllNodes, [&](CNode* pnode) { if (pnode->fMasternode) { #ifdef ENABLE_WALLET bool fFound = false; - for (const auto& mnInfo : vecMnInfo) { - if (pnode->addr == mnInfo.addr) { + for (const auto& dmn : vecDmns) { + if (pnode->addr == dmn->pdmnState->addr) { fFound = true; break; } diff --git a/src/masternodeman.h b/src/masternodeman.h index a2cb7c2c2b..58c3ff91b6 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -140,6 +140,7 @@ public: bool IsValidForMixingTxes(const COutPoint &outpoint); bool AllowMixing(const COutPoint &outpoint); bool DisallowMixing(const COutPoint &outpoint); + int64_t GetLastDsq(const COutPoint &outpoint); /// Check all Masternodes void Check(); diff --git a/src/privatesend-client.cpp b/src/privatesend-client.cpp index 13b43e97f8..6b80989238 100644 --- a/src/privatesend-client.cpp +++ b/src/privatesend-client.cpp @@ -61,12 +61,12 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& if (dsq.IsExpired()) return; - masternode_info_t infoMn; - if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, infoMn)) return; + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint); + if (!dmn) return; - if (!dsq.CheckSignature(infoMn.legacyKeyIDOperator, infoMn.blsPubKeyOperator)) { - // we probably have outdated info - mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman); + if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) { + // TODO ban? return; } @@ -74,9 +74,9 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& if (dsq.fReady) { LOCK(cs_deqsessions); for (auto& session : deqSessions) { - masternode_info_t mnMixing; - if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing.addr == infoMn.addr && session.GetState() == POOL_STATE_QUEUE) { - LogPrint("privatesend", "DSQUEUE -- PrivateSend queue (%s) is ready on masternode %s\n", dsq.ToString(), infoMn.addr.ToString()); + CDeterministicMNCPtr mnMixing; + if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->pdmnState->addr == dmn->pdmnState->addr && session.GetState() == POOL_STATE_QUEUE) { + LogPrint("privatesend", "DSQUEUE -- PrivateSend queue (%s) is ready on masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); session.SubmitDenominate(connman); return; } @@ -89,25 +89,26 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& for (const auto& q : vecPrivateSendQueue) { if (q.masternodeOutpoint == dsq.masternodeOutpoint) { // no way same mn can send another "not yet ready" dsq this soon - LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", infoMn.addr.ToString()); + LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->ToString()); return; } } - int nThreshold = infoMn.nLastDsq + mnodeman.CountMasternodes() / 5; - LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", infoMn.nLastDsq, nThreshold, mnodeman.nDsqCount); + int64_t nLastDsq = mnodeman.GetLastDsq(dsq.masternodeOutpoint); + int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5; + LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mnodeman.nDsqCount); //don't allow a few nodes to dominate the queuing process - if (infoMn.nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) { - LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", infoMn.addr.ToString()); + if (nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) { + LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString()); return; } if (!mnodeman.AllowMixing(dsq.masternodeOutpoint)) return; - LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), infoMn.addr.ToString()); + LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); for (auto& session : deqSessions) { - masternode_info_t mnMixing; - if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing.outpoint == dsq.masternodeOutpoint) { + CDeterministicMNCPtr mnMixing; + if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->collateralOutpoint == dsq.masternodeOutpoint) { dsq.fTried = true; } } @@ -139,8 +140,8 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& return; } - if (!infoMixingMasternode.fInfoValid) return; - if (infoMixingMasternode.addr != pfrom->addr) { + if (!mixingMasternode) return; + if (mixingMasternode->pdmnState->addr != pfrom->addr) { //LogPrintf("DSSTATUSUPDATE -- message doesn't match current Masternode: infoMixingMasternode %s addr %s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString()); return; } @@ -181,8 +182,8 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& return; } - if (!infoMixingMasternode.fInfoValid) return; - if (infoMixingMasternode.addr != pfrom->addr) { + if (!mixingMasternode) return; + if (mixingMasternode->pdmnState->addr != pfrom->addr) { //LogPrintf("DSFINALTX -- message doesn't match current Masternode: infoMixingMasternode %s addr %s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString()); return; } @@ -208,9 +209,9 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& return; } - if (!infoMixingMasternode.fInfoValid) return; - if (infoMixingMasternode.addr != pfrom->addr) { - LogPrint("privatesend", "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", infoMixingMasternode.addr.ToString(), pfrom->addr.ToString()); + if (!mixingMasternode) return; + if (mixingMasternode->pdmnState->addr != pfrom->addr) { + LogPrint("privatesend", "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", mixingMasternode->pdmnState->addr.ToString(), pfrom->addr.ToString()); return; } @@ -258,7 +259,7 @@ void CPrivateSendClientSession::SetNull() // Client side nEntriesCount = 0; fLastEntryAccepted = false; - infoMixingMasternode = masternode_info_t(); + mixingMasternode = nullptr; pendingDsaRequest = CPendingDsaRequest(); CPrivateSendBaseSession::SetNull(); @@ -368,22 +369,22 @@ std::string CPrivateSendClientManager::GetSessionDenoms() return strSessionDenoms.empty() ? "N/A" : strSessionDenoms; } -bool CPrivateSendClientSession::GetMixingMasternodeInfo(masternode_info_t& mnInfoRet) const +bool CPrivateSendClientSession::GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const { - mnInfoRet = infoMixingMasternode.fInfoValid ? infoMixingMasternode : masternode_info_t(); - return infoMixingMasternode.fInfoValid; + ret = mixingMasternode; + return ret != nullptr; } -bool CPrivateSendClientManager::GetMixingMasternodesInfo(std::vector& vecMnInfoRet) const +bool CPrivateSendClientManager::GetMixingMasternodesInfo(std::vector& vecDmnsRet) const { LOCK(cs_deqsessions); for (const auto& session : deqSessions) { - masternode_info_t mnInfo; - if (session.GetMixingMasternodeInfo(mnInfo)) { - vecMnInfoRet.push_back(mnInfo); + CDeterministicMNCPtr dmn; + if (session.GetMixingMasternodeInfo(dmn)) { + vecDmnsRet.push_back(dmn); } } - return !vecMnInfoRet.empty(); + return !vecDmnsRet.empty(); } // @@ -578,7 +579,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr if (!pwalletMain) return false; if (fMasternodeMode || pnode == nullptr) return false; - if (!infoMixingMasternode.fInfoValid) return false; + if (!mixingMasternode) return false; finalMutableTransaction = finalTransactionNew; LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- finalMutableTransaction=%s", finalMutableTransaction.ToString()); @@ -588,7 +589,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr sort(finalMutableTransaction.vout.begin(), finalMutableTransaction.vout.end(), CompareOutputBIP69()); if (finalMutableTransaction.GetHash() != finalTransactionNew.GetHash()) { - LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- WARNING! Masternode %s is not BIP69 compliant!\n", infoMixingMasternode.outpoint.ToStringShort()); + LogPrintf("CPrivateSendClientSession::SignFinalTransaction -- WARNING! Masternode %s is not BIP69 compliant!\n", mixingMasternode->proTxHash.ToString()); UnlockCoins(); keyHolderStorage.ReturnAll(); SetNull(); @@ -832,7 +833,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool return false; } - if (mnodeman.size() == 0) { + if (deterministicMNManager->GetListAtChainTip().GetValidMNsCount() == 0) { LogPrint("privatesend", "CPrivateSendClientSession::DoAutomaticDenominating -- No Masternodes detected\n"); strAutoDenomResult = _("No Masternodes detected."); return false; @@ -952,7 +953,7 @@ bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool return false; } - int nMnCountEnabled = mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION); + int nMnCountEnabled = deterministicMNManager->GetListAtChainTip().GetValidMNsCount(); // If we've used 90% of the Masternode list then drop the oldest first ~30% int nThreshold_high = nMnCountEnabled * 0.9; @@ -999,22 +1000,22 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize { if (!pwalletMain) return false; + auto mnList = deterministicMNManager->GetListAtChainTip(); + std::vector vecStandardDenoms = CPrivateSend::GetStandardDenominations(); // Look through the queues and see if anything matches CPrivateSendQueue dsq; while (privateSendClient.GetQueueItemAndTry(dsq)) { - masternode_info_t infoMn; + auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint); - if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, infoMn)) { + if (!dmn) { LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- dsq masternode is not in masternode list, masternode=%s\n", dsq.masternodeOutpoint.ToStringShort()); continue; } - if (infoMn.nProtocolVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) continue; - // skip next mn payments winners - if (mnpayments.IsScheduled(infoMn, 0)) { - LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", infoMn.outpoint.ToStringShort()); + if (mnpayments.IsScheduled(dmn, 0)) { + LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString()); continue; } @@ -1042,20 +1043,20 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize privateSendClient.AddUsedMasternode(dsq.masternodeOutpoint); - if (connman.IsMasternodeOrDisconnectRequested(infoMn.addr)) { - LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", infoMn.addr.ToString()); + if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) { + LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString()); continue; } nSessionDenom = dsq.nDenom; - infoMixingMasternode = infoMn; - pendingDsaRequest = CPendingDsaRequest(infoMn.addr, CPrivateSendAccept(nSessionDenom, txMyCollateral)); - connman.AddPendingMasternode(infoMn.addr); + mixingMasternode = dmn; + pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral)); + connman.AddPendingMasternode(dmn->pdmnState->addr); // TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION SetState(POOL_STATE_QUEUE); nTimeLastSuccessfulStep = GetTime(); LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- pending connection (from queue): nSessionDenom: %d (%s), addr=%s\n", - nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), infoMn.addr.ToString()); + nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), dmn->pdmnState->addr.ToString()); strAutoDenomResult = _("Trying to connect..."); return true; } @@ -1068,7 +1069,7 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc if (!pwalletMain) return false; int nTries = 0; - int nMnCount = mnodeman.CountMasternodes(); + int nMnCount = deterministicMNManager->GetListAtChainTip().GetValidMNsCount(); // ** find the coins we'll use std::vector vecTxIn; @@ -1082,39 +1083,40 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc // otherwise, try one randomly while (nTries < 10) { - masternode_info_t infoMn = privateSendClient.GetNotUsedMasternode(); + auto dmn = privateSendClient.GetRandomNotUsedMasternode(); - if (!infoMn.fInfoValid) { + if (!dmn) { LogPrintf("CPrivateSendClientSession::StartNewQueue -- Can't find random masternode!\n"); strAutoDenomResult = _("Can't find random Masternode."); return false; } - privateSendClient.AddUsedMasternode(infoMn.outpoint); + privateSendClient.AddUsedMasternode(dmn->collateralOutpoint); // skip next mn payments winners - if (mnpayments.IsScheduled(infoMn, 0)) { - LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping winner, masternode=%s\n", infoMn.outpoint.ToStringShort()); + if (mnpayments.IsScheduled(dmn, 0)) { + LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping winner, masternode=%s\n", dmn->proTxHash.ToString()); nTries++; continue; } - if (infoMn.nLastDsq != 0 && infoMn.nLastDsq + nMnCount / 5 > mnodeman.nDsqCount) { + int64_t nLastDsq = mnodeman.GetLastDsq(dmn->collateralOutpoint); + if (nLastDsq != 0 && nLastDsq + nMnCount / 5 > mnodeman.nDsqCount) { LogPrintf("CPrivateSendClientSession::StartNewQueue -- Too early to mix on this masternode!" " masternode=%s addr=%s nLastDsq=%d CountEnabled/5=%d nDsqCount=%d\n", - infoMn.outpoint.ToStringShort(), infoMn.addr.ToString(), infoMn.nLastDsq, + dmn->proTxHash.ToString(), dmn->pdmnState->addr.ToString(), nLastDsq, nMnCount / 5, mnodeman.nDsqCount); nTries++; continue; } - if (connman.IsMasternodeOrDisconnectRequested(infoMn.addr)) { - LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", infoMn.addr.ToString()); + if (connman.IsMasternodeOrDisconnectRequested(dmn->pdmnState->addr)) { + LogPrintf("CPrivateSendClientSession::StartNewQueue -- skipping masternode connection, addr=%s\n", dmn->pdmnState->addr.ToString()); nTries++; continue; } - LogPrintf("CPrivateSendClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, infoMn.addr.ToString()); + LogPrintf("CPrivateSendClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, dmn->pdmnState->addr.ToString()); std::vector vecAmounts; pwalletMain->ConvertList(vecTxIn, vecAmounts); @@ -1123,14 +1125,14 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nValueMin, CAmount nBalanc nSessionDenom = CPrivateSend::GetDenominationsByAmounts(vecAmounts); } - infoMixingMasternode = infoMn; - connman.AddPendingMasternode(infoMn.addr); - pendingDsaRequest = CPendingDsaRequest(infoMn.addr, CPrivateSendAccept(nSessionDenom, txMyCollateral)); + mixingMasternode = dmn; + connman.AddPendingMasternode(dmn->pdmnState->addr); + pendingDsaRequest = CPendingDsaRequest(dmn->pdmnState->addr, CPrivateSendAccept(nSessionDenom, txMyCollateral)); // TODO: add new state POOL_STATE_CONNECTING and bump MIN_PRIVATESEND_PEER_PROTO_VERSION SetState(POOL_STATE_QUEUE); nTimeLastSuccessfulStep = GetTime(); LogPrintf("CPrivateSendClientSession::StartNewQueue -- pending connection, nSessionDenom: %d (%s), addr=%s\n", - nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), infoMn.addr.ToString()); + nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom), dmn->pdmnState->addr.ToString()); strAutoDenomResult = _("Trying to connect..."); return true; } @@ -1596,9 +1598,9 @@ bool CPrivateSendClientSession::CreateDenominated(const CompactTallyItem& tallyI void CPrivateSendClientSession::RelayIn(const CPrivateSendEntry& entry, CConnman& connman) { - if (!infoMixingMasternode.fInfoValid) return; + if (!mixingMasternode) return; - connman.ForNode(infoMixingMasternode.addr, [&entry, &connman](CNode* pnode) { + connman.ForNode(mixingMasternode->pdmnState->addr, [&entry, &connman](CNode* pnode) { LogPrintf("CPrivateSendClientSession::RelayIn -- found master, relaying message to %s\n", pnode->addr.ToString()); CNetMsgMaker msgMaker(pnode->GetSendVersion()); connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSVIN, entry)); diff --git a/src/privatesend-client.h b/src/privatesend-client.h index aec8a97d3d..245089793e 100644 --- a/src/privatesend-client.h +++ b/src/privatesend-client.h @@ -10,8 +10,11 @@ #include "privatesend.h" #include "wallet/wallet.h" +#include "evo/deterministicmns.h" + class CPrivateSendClientManager; class CConnman; +class CNode; static const int DENOMS_COUNT_MAX = 100; @@ -92,7 +95,7 @@ private: std::string strLastMessage; std::string strAutoDenomResult; - masternode_info_t infoMixingMasternode; + CDeterministicMNCPtr mixingMasternode; CMutableTransaction txMyCollateral; // client side collateral CPendingDsaRequest pendingDsaRequest; @@ -139,7 +142,7 @@ public: fLastEntryAccepted(false), strLastMessage(), strAutoDenomResult(), - infoMixingMasternode(), + mixingMasternode(), txMyCollateral(), pendingDsaRequest(), keyHolderStorage() @@ -154,7 +157,7 @@ public: std::string GetStatus(bool fWaitForBlock); - bool GetMixingMasternodeInfo(masternode_info_t& mnInfoRet) const; + bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const; /// Passively run mixing in the background according to the configuration in settings bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false); @@ -235,7 +238,7 @@ public: std::string GetStatuses(); std::string GetSessionDenoms(); - bool GetMixingMasternodesInfo(std::vector& vecMnInfoRet) const; + bool GetMixingMasternodesInfo(std::vector& vecDmnsRet) const; /// Passively run mixing in the background according to the configuration in settings bool DoAutomaticDenominating(CConnman& connman, bool fDryRun = false); diff --git a/src/privatesend-server.cpp b/src/privatesend-server.cpp index 57f8267f67..51472a21ba 100644 --- a/src/privatesend-server.cpp +++ b/src/privatesend-server.cpp @@ -44,8 +44,9 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm LogPrint("privatesend", "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CPrivateSend::GetDenominationsToString(dsa.nDenom), dsa.txCollateral.ToString()); - masternode_info_t mnInfo; - if (!mnodeman.GetMasternodeInfo(activeMasternodeInfo.outpoint, mnInfo)) { + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto dmn = mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint); + if (!dmn) { PushStatus(pfrom, STATUS_REJECTED, ERR_MN_LIST, connman); return; } @@ -65,7 +66,8 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm } } - if (mnInfo.nLastDsq != 0 && mnInfo.nLastDsq + mnodeman.CountMasternodes() / 5 > mnodeman.nDsqCount) { + int64_t nLastDsq = mnodeman.GetLastDsq(dmn->collateralOutpoint); + if (nLastDsq != 0 && nLastDsq + mnList.GetValidMNsCount() / 5 > mnodeman.nDsqCount) { LogPrintf("DSACCEPT -- last dsq too recent, must wait: addr=%s\n", pfrom->addr.ToString()); PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT, connman); return; @@ -111,12 +113,12 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (dsq.IsExpired()) return; - masternode_info_t mnInfo; - if (!mnodeman.GetMasternodeInfo(dsq.masternodeOutpoint, mnInfo)) return; + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint); + if (!dmn) return; - if (!dsq.CheckSignature(mnInfo.legacyKeyIDOperator, mnInfo.blsPubKeyOperator)) { - // we probably have outdated info - mnodeman.AskForMN(pfrom, dsq.masternodeOutpoint, connman); + if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) { + // TODO ban? return; } @@ -124,21 +126,22 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm for (const auto& q : vecPrivateSendQueue) { if (q.masternodeOutpoint == dsq.masternodeOutpoint) { // no way same mn can send another "not yet ready" dsq this soon - LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", mnInfo.addr.ToString()); + LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->addr.ToString()); return; } } - int nThreshold = mnInfo.nLastDsq + mnodeman.CountMasternodes() / 5; - LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", mnInfo.nLastDsq, nThreshold, mnodeman.nDsqCount); + int64_t nLastDsq = mnodeman.GetLastDsq(dmn->collateralOutpoint); + int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5; + LogPrint("privatesend", "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mnodeman.nDsqCount); //don't allow a few nodes to dominate the queuing process - if (mnInfo.nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) { - LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", mnInfo.addr.ToString()); + if (nLastDsq != 0 && nThreshold > mnodeman.nDsqCount) { + LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->pdmnState->addr.ToString()); return; } mnodeman.AllowMixing(dsq.masternodeOutpoint); - LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), mnInfo.addr.ToString()); + LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); vecPrivateSendQueue.push_back(dsq); dsq.Relay(connman); } diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 87d8497648..e98ea85a3f 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -99,13 +99,13 @@ UniValue getpoolinfo(const JSONRPCRequest& request) // obj.push_back(Pair("entries", pprivateSendBase->GetEntriesCount())); obj.push_back(Pair("status", privateSendClient.GetStatuses())); - std::vector vecMnInfo; - if (privateSendClient.GetMixingMasternodesInfo(vecMnInfo)) { + std::vector vecDmns; + if (privateSendClient.GetMixingMasternodesInfo(vecDmns)) { UniValue pools(UniValue::VARR); - for (const auto& mnInfo : vecMnInfo) { + for (const auto& dmn : vecDmns) { UniValue pool(UniValue::VOBJ); - pool.push_back(Pair("outpoint", mnInfo.outpoint.ToStringShort())); - pool.push_back(Pair("addr", mnInfo.addr.ToString())); + pool.push_back(Pair("outpoint", dmn->collateralOutpoint.ToStringShort())); + pool.push_back(Pair("addr", dmn->pdmnState->addr.ToString())); pools.push_back(pool); } obj.push_back(Pair("pools", pools)); From 71a695100813fdc5b1afa96da32bf517268125f4 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 15:47:57 +0100 Subject: [PATCH 14/26] Move logic from FindRandomNotInVec into GetRandomNotUsedMasternode And adapt it to directly use deterministicMNManager --- src/masternodeman.cpp | 45 -------------------------------------- src/masternodeman.h | 3 --- src/privatesend-client.cpp | 38 ++++++++++++++++++++++++++++++-- src/privatesend-client.h | 2 +- 4 files changed, 37 insertions(+), 51 deletions(-) diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 88b86a9247..71980c9ad1 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -747,51 +747,6 @@ bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool f return mnInfoRet.fInfoValid; } -masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector &vecToExclude, int nProtocolVersion) -{ - LOCK(cs); - - nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion; - - int nCountEnabled = CountEnabled(nProtocolVersion); - int nCountNotExcluded = nCountEnabled - vecToExclude.size(); - - LogPrintf("CMasternodeMan::FindRandomNotInVec -- %d enabled masternodes, %d masternodes to choose from\n", nCountEnabled, nCountNotExcluded); - if(nCountNotExcluded < 1) return masternode_info_t(); - - // fill a vector of pointers - std::vector vpMasternodesShuffled; - for (const auto& mnpair : mapMasternodes) { - vpMasternodesShuffled.push_back(&mnpair.second); - } - - FastRandomContext insecure_rand; - // shuffle pointers - std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecure_rand); - bool fExclude; - - // loop through - for (const auto& pmn : vpMasternodesShuffled) { - if(pmn->nProtocolVersion < nProtocolVersion || !pmn->IsEnabled()) continue; - fExclude = false; - for (const auto& outpointToExclude : vecToExclude) { - if(pmn->outpoint == outpointToExclude) { - fExclude = true; - break; - } - } - if(fExclude) continue; - if (deterministicMNManager->IsDIP3Active() && !deterministicMNManager->HasValidMNCollateralAtChainTip(pmn->outpoint)) - continue; - // found the one not in vecToExclude - LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- found, masternode=%s\n", pmn->outpoint.ToStringShort()); - return pmn->GetInfo(); - } - - LogPrint("masternode", "CMasternodeMan::FindRandomNotInVec -- failed\n"); - return masternode_info_t(); -} - std::map CMasternodeMan::GetFullMasternodeMap() { LOCK(cs); diff --git a/src/masternodeman.h b/src/masternodeman.h index 58c3ff91b6..695229a96c 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -182,9 +182,6 @@ public: /// Same as above but use current block height bool GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCountRet, masternode_info_t& mnInfoRet); - /// Find a random entry - masternode_info_t FindRandomNotInVec(const std::vector &vecToExclude, int nProtocolVersion = -1); - std::map GetFullMasternodeMap(); bool GetMasternodeRanks(rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight = -1, int nMinProtocol = 0); diff --git a/src/privatesend-client.cpp b/src/privatesend-client.cpp index 6b80989238..98590e8a78 100644 --- a/src/privatesend-client.cpp +++ b/src/privatesend-client.cpp @@ -991,9 +991,43 @@ void CPrivateSendClientManager::AddUsedMasternode(const COutPoint& outpointMn) vecMasternodesUsed.push_back(outpointMn); } -masternode_info_t CPrivateSendClientManager::GetNotUsedMasternode() +CDeterministicMNCPtr CPrivateSendClientManager::GetRandomNotUsedMasternode() { - return mnodeman.FindRandomNotInVec(vecMasternodesUsed, MIN_PRIVATESEND_PEER_PROTO_VERSION); + auto mnList = deterministicMNManager->GetListAtChainTip(); + + int nCountEnabled = mnList.GetValidMNsCount(); + int nCountNotExcluded = nCountEnabled - vecMasternodesUsed.size(); + + LogPrintf("CPrivateSendClientManager::%s -- %d enabled masternodes, %d masternodes to choose from\n", __func__, nCountEnabled, nCountNotExcluded); + if(nCountNotExcluded < 1) { + return nullptr; + } + + // fill a vector + std::vector vpMasternodesShuffled; + vpMasternodesShuffled.reserve((size_t)nCountEnabled); + mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) { + vpMasternodesShuffled.emplace_back(dmn); + }); + + FastRandomContext insecure_rand; + // shuffle pointers + std::random_shuffle(vpMasternodesShuffled.begin(), vpMasternodesShuffled.end(), insecure_rand); + + std::set excludeSet(vecMasternodesUsed.begin(), vecMasternodesUsed.end()); + + // loop through + for (const auto& dmn : vpMasternodesShuffled) { + if (excludeSet.count(dmn->collateralOutpoint)) { + continue; + } + + LogPrint("masternode", "CPrivateSendClientManager::%s -- found, masternode=%s\n", __func__, dmn->collateralOutpoint.ToStringShort()); + return dmn; + } + + LogPrint("masternode", "CPrivateSendClientManager::%s -- failed\n", __func__); + return nullptr; } bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman) diff --git a/src/privatesend-client.h b/src/privatesend-client.h index 245089793e..1ab1b31c15 100644 --- a/src/privatesend-client.h +++ b/src/privatesend-client.h @@ -248,7 +248,7 @@ public: void ProcessPendingDsaRequest(CConnman& connman); void AddUsedMasternode(const COutPoint& outpointMn); - masternode_info_t GetNotUsedMasternode(); + CDeterministicMNCPtr GetRandomNotUsedMasternode(); void UpdatedSuccessBlock(); From 17c792cd3bc5c69e62d2e3747fe5e7364fdfeb3a Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 15:49:04 +0100 Subject: [PATCH 15/26] Remove MN upgrade check in ComputeBlockVersion Has to be replaced with something new in the future. --- src/validation.cpp | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 786c68fbeb..e51e3034cd 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1828,35 +1828,7 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para ThresholdState state = VersionBitsState(pindexPrev, params, pos, versionbitscache); const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; if (vbinfo.check_mn_protocol && state == THRESHOLD_STARTED && fCheckMasternodesUpgraded) { - if (deterministicMNManager->IsDIP3Active()) { - auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash()); - auto payee = mnList.GetMNPayee(); - if (!payee) { - continue; - } - } else { - std::vector voutMasternodePayments; - masternode_info_t mnInfo; - if (!mnpayments.GetBlockTxOuts(pindexPrev->nHeight + 1, 0, voutMasternodePayments)) { - // no votes for this block - continue; - } - bool mnKnown = false; - for (const auto& txout : voutMasternodePayments) { - if (mnodeman.GetMasternodeInfo(txout.scriptPubKey, mnInfo)) { - mnKnown = true; - break; - } - } - if (!mnKnown) { - // unknown masternode - continue; - } - if (mnInfo.nProtocolVersion < DMN_PROTO_VERSION) { - // masternode is not upgraded yet - continue; - } - } + // TODO implement new logic for MN upgrade checks (e.g. with LLMQ based feature/version voting) } if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) { nVersion |= VersionBitsMask(params, (Consensus::DeploymentPos)i); From 37541ee00ec1ebf19a53ba28a8d67912da95303e Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 16:09:07 +0100 Subject: [PATCH 16/26] Change GetMasternodeScores and GetMasternodeRank/s to use CDeterministicMNCPtr This leaves us with nMinProtocol unused, but this is ok as we will later remove that argument completely. --- src/instantx.cpp | 6 ++--- src/masternode-payments.cpp | 8 +++--- src/masternodeman.cpp | 51 +++++++++++++------------------------ src/masternodeman.h | 8 +++--- 4 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index b598bc8713..2afb982dd3 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -245,8 +245,7 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman) int nRank; uint256 quorumModifierHash; - int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto()); - if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) { + if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight)) { LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternodeInfo.outpoint.ToStringShort()); continue; } @@ -1061,8 +1060,7 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const int nRank; uint256 expectedQuorumModifierHash; - int nMinRequiredProtocol = std::max(MIN_INSTANTSEND_PROTO_VERSION, mnpayments.GetMinMasternodePaymentsProto()); - if (!mnodeman.GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight, nMinRequiredProtocol)) { + if (!mnodeman.GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight)) { //can be caused by past versions trying to vote with an invalid protocol LogPrint("instantsend", "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort()); return false; diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index 99a647178c..87ff0dcf8d 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -1046,7 +1046,7 @@ void CMasternodePayments::CheckBlockVotes(int nBlockHeight) voteHash.ToString()); continue; } - if (itVote->second.masternodeOutpoint == mn.second.outpoint) { + if (itVote->second.masternodeOutpoint == mn.second->collateralOutpoint) { payee = itVote->second.payee; found = true; break; @@ -1061,12 +1061,12 @@ void CMasternodePayments::CheckBlockVotes(int nBlockHeight) CBitcoinAddress address2(address1); debugStr += strprintf(" - %s - voted for %s\n", - mn.second.outpoint.ToStringShort(), address2.ToString()); + mn.second->collateralOutpoint.ToStringShort(), address2.ToString()); } else { - mapMasternodesDidNotVote.emplace(mn.second.outpoint, 0).first->second++; + mapMasternodesDidNotVote.emplace(mn.second->collateralOutpoint, 0).first->second++; debugStr += strprintf(" - %s - no vote received\n", - mn.second.outpoint.ToStringShort()); + mn.second->collateralOutpoint.ToStringShort()); } if (++i >= MNPAYMENTS_SIGNATURES_TOTAL) break; diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 71980c9ad1..aa696e8405 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -42,10 +42,10 @@ struct CompareLastPaidBlock struct CompareScoreMN { - bool operator()(const std::pair& t1, - const std::pair& t2) const + bool operator()(const std::pair& t1, + const std::pair& t2) const { - return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->outpoint < t2.second->outpoint); + return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->collateralOutpoint < t2.second->collateralOutpoint); } }; @@ -257,9 +257,9 @@ void CMasternodeMan::CheckAndRemove(CConnman& connman) // ask first MNB_RECOVERY_QUORUM_TOTAL masternodes we can connect to and we haven't asked recently for(int i = 0; setRequested.size() < MNB_RECOVERY_QUORUM_TOTAL && i < (int)vecMasternodeRanks.size(); i++) { // avoid banning - if(mWeAskedForMasternodeListEntry.count(it->first) && mWeAskedForMasternodeListEntry[it->first].count(vecMasternodeRanks[i].second.addr)) continue; + if(mWeAskedForMasternodeListEntry.count(it->first) && mWeAskedForMasternodeListEntry[it->first].count(vecMasternodeRanks[i].second->pdmnState->addr)) continue; // didn't ask recently, ok to ask now - CService addr = vecMasternodeRanks[i].second.addr; + CService addr = vecMasternodeRanks[i].second->pdmnState->addr; setRequested.insert(addr); listScheduledMnbRequestConnections.push_back(std::make_pair(addr, hash)); fAskedForMnbRecovery = true; @@ -766,33 +766,18 @@ std::map CMasternodeMan::GetFullMasternodeMap() } } -bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol) +bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet) { AssertLockHeld(cs); vecMasternodeScoresRet.clear(); - if (deterministicMNManager->IsDIP3Active()) { - auto mnList = deterministicMNManager->GetListAtChainTip(); - auto scores = mnList.CalculateScores(nBlockHash); - for (const auto& p : scores) { - auto* mn = Find(p.second->collateralOutpoint); - vecMasternodeScoresRet.emplace_back(p.first, mn); - } - } else { - if (!masternodeSync.IsMasternodeListSynced()) - return false; - - if (mapMasternodes.empty()) - return false; - - // calculate scores - for (const auto& mnpair : mapMasternodes) { - if (mnpair.second.nProtocolVersion >= nMinProtocol) { - vecMasternodeScoresRet.push_back(std::make_pair(mnpair.second.CalculateScore(nBlockHash), &mnpair.second)); - } - } + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto scores = mnList.CalculateScores(nBlockHash); + for (const auto& p : scores) { + vecMasternodeScoresRet.emplace_back(p.first, p.second); } + sort(vecMasternodeScoresRet.rbegin(), vecMasternodeScoresRet.rend(), CompareScoreMN()); return !vecMasternodeScoresRet.empty(); } @@ -820,13 +805,13 @@ bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, LOCK(cs); score_pair_vec_t vecMasternodeScores; - if (!GetMasternodeScores(blockHashRet, vecMasternodeScores, nMinProtocol)) + if (!GetMasternodeScores(blockHashRet, vecMasternodeScores)) return false; int nRank = 0; for (const auto& scorePair : vecMasternodeScores) { nRank++; - if(scorePair.second->outpoint == outpoint) { + if(scorePair.second->collateralOutpoint == outpoint) { nRankRet = nRank; return true; } @@ -852,13 +837,13 @@ bool CMasternodeMan::GetMasternodeRanks(CMasternodeMan::rank_pair_vec_t& vecMast LOCK(cs); score_pair_vec_t vecMasternodeScores; - if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol)) + if (!GetMasternodeScores(nBlockHash, vecMasternodeScores)) return false; int nRank = 0; for (const auto& scorePair : vecMasternodeScores) { nRank++; - vecMasternodeRanksRet.push_back(std::make_pair(nRank, *scorePair.second)); + vecMasternodeRanksRet.push_back(std::make_pair(nRank, scorePair.second)); } return true; @@ -1188,7 +1173,7 @@ void CMasternodeMan::DoFullVerificationStep(CConnman& connman) (int)MAX_POSE_RANK); return; } - if(rankPair.second.outpoint == activeMasternodeInfo.outpoint) { + if(rankPair.second->collateralOutpoint == activeMasternodeInfo.outpoint) { nMyRank = rankPair.first; LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Found self at rank %d/%d, verifying up to %d masternodes\n", nMyRank, nRanksTotal, (int)MAX_POSE_CONNECTIONS); @@ -1218,8 +1203,8 @@ void CMasternodeMan::DoFullVerificationStep(CConnman& connman) continue; } LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Verifying masternode %s rank %d/%d address %s\n", - it->second.outpoint.ToStringShort(), it->first, nRanksTotal, it->second.addr.ToString()); - CAddress addr = CAddress(it->second.addr, NODE_NETWORK); + it->second->collateralOutpoint.ToStringShort(), it->first, nRanksTotal, it->second->pdmnState->addr.ToString()); + CAddress addr = CAddress(it->second->pdmnState->addr, NODE_NETWORK); if(CheckVerifyRequestAddr(addr, connman)) { vAddr.push_back(addr); if((int)vAddr.size() >= MAX_POSE_CONNECTIONS) break; diff --git a/src/masternodeman.h b/src/masternodeman.h index 695229a96c..aa30b2e4fc 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -8,6 +8,8 @@ #include "masternode.h" #include "sync.h" +#include "evo/deterministicmns.h" + class CMasternodeMan; class CConnman; @@ -16,9 +18,9 @@ extern CMasternodeMan mnodeman; class CMasternodeMan { public: - typedef std::pair score_pair_t; + typedef std::pair score_pair_t; typedef std::vector score_pair_vec_t; - typedef std::pair rank_pair_t; + typedef std::pair rank_pair_t; typedef std::vector rank_pair_vec_t; private: @@ -80,7 +82,7 @@ private: /// Find an entry CMasternode* Find(const COutPoint& outpoint); - bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol = 0); + bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet); void SyncSingle(CNode* pnode, const COutPoint& outpoint, CConnman& connman); void SyncAll(CNode* pnode, CConnman& connman); From 0594cd71978ff3a5c06c2a07cbedb844702adaef Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 28 Dec 2018 08:35:39 +0100 Subject: [PATCH 17/26] Remove code that is incompatible now due to GetMasternodeRanks returning DMNs now It's ok to remove this code as we're later going to completely remove it. Until then, this code is dead nevertheless. --- src/masternodeman.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index aa696e8405..8ef74f5cf1 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -699,7 +699,7 @@ bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool f if(mnpair.second.nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) continue; //it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it - if(mnpayments.IsScheduled(mnpair.second, nBlockHeight)) continue; + //if(mnpayments.IsScheduled(mnpair.second, nBlockHeight)) continue; //it's too new, wait for a cycle if(fFilterSigTime && mnpair.second.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue; @@ -1191,17 +1191,17 @@ void CMasternodeMan::DoFullVerificationStep(CConnman& connman) auto it = vecMasternodeRanks.begin() + nOffset; while(it != vecMasternodeRanks.end()) { - if(it->second.IsPoSeVerified() || it->second.IsPoSeBanned()) { - LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Already %s%s%s masternode %s address %s, skipping...\n", - it->second.IsPoSeVerified() ? "verified" : "", - it->second.IsPoSeVerified() && it->second.IsPoSeBanned() ? " and " : "", - it->second.IsPoSeBanned() ? "banned" : "", - it->second.outpoint.ToStringShort(), it->second.addr.ToString()); - nOffset += MAX_POSE_CONNECTIONS; - if(nOffset >= (int)vecMasternodeRanks.size()) break; - it += MAX_POSE_CONNECTIONS; - continue; - } +// if(it->second.IsPoSeVerified() || it->second.IsPoSeBanned()) { +// LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Already %s%s%s masternode %s address %s, skipping...\n", +// it->second.IsPoSeVerified() ? "verified" : "", +// it->second.IsPoSeVerified() && it->second.IsPoSeBanned() ? " and " : "", +// it->second.IsPoSeBanned() ? "banned" : "", +// it->second.outpoint.ToStringShort(), it->second.addr.ToString()); +// nOffset += MAX_POSE_CONNECTIONS; +// if(nOffset >= (int)vecMasternodeRanks.size()) break; +// it += MAX_POSE_CONNECTIONS; +// continue; +// } LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Verifying masternode %s rank %d/%d address %s\n", it->second->collateralOutpoint.ToStringShort(), it->first, nRanksTotal, it->second->pdmnState->addr.ToString()); CAddress addr = CAddress(it->second->pdmnState->addr, NODE_NETWORK); From 4c3bb73045446ac75d79713501566488c0189acd Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 16:11:06 +0100 Subject: [PATCH 18/26] Remove call to mnodeman.PoSeBan --- src/instantx.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index 2afb982dd3..dbe7e848ea 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -468,7 +468,8 @@ void CInstantSend::UpdateVotedOutpoints(const CTxLockVote& vote, CTxLockCandidat txLockCandidate.MarkOutpointAsAttacked(vote.GetOutpoint()); it2->second.MarkOutpointAsAttacked(vote.GetOutpoint()); // apply maximum PoSe ban score to this masternode i.e. PoSe-ban it instantly - mnodeman.PoSeBan(vote.GetMasternodeOutpoint()); + // TODO Call new PoSe system when it's ready + //mnodeman.PoSeBan(vote.GetMasternodeOutpoint()); // NOTE: This vote must be relayed further to let all other nodes know about such // misbehaviour of this masternode. This way they should also be able to construct // conflicting lock and PoSe-ban this masternode. From 4b150e72f1b83f462037d1c63057dd119ebae9ed Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 16:27:17 +0100 Subject: [PATCH 19/26] Directly use deterministicMNManager instead of mnodeman.CountXXX --- src/qt/clientmodel.cpp | 8 ++++---- src/rpc/masternode.cpp | 26 +++++--------------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 07ff4ddcbb..8d506d918b 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -83,10 +83,10 @@ int ClientModel::getNumConnections(unsigned int flags) const QString ClientModel::getMasternodeCountString() const { // return tr("Total: %1 (PS compatible: %2 / Enabled: %3) (IPv4: %4, IPv6: %5, TOR: %6)").arg(QString::number((int)mnodeman.size())) - return tr("Total: %1 (PS compatible: %2 / Enabled: %3)") - .arg(QString::number((int)mnodeman.CountMasternodes(0))) - .arg(QString::number((int)mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION))) - .arg(QString::number((int)mnodeman.CountEnabled())); + auto mnList = deterministicMNManager->GetListAtChainTip(); + return tr("Total: %1 (Enabled: %2)") + .arg(QString::number((int)mnList.GetAllMNsCount())) + .arg(QString::number((int)mnList.GetValidMNsCount())); // .arg(QString::number((int)mnodeman.CountByIP(NET_IPV4))) // .arg(QString::number((int)mnodeman.CountByIP(NET_IPV6))) // .arg(QString::number((int)mnodeman.CountByIP(NET_TOR))); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index e98ea85a3f..c7d2d85894 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -224,25 +224,15 @@ UniValue masternode_count(const JSONRPCRequest& request) if (request.fHelp || request.params.size() > 2) masternode_count_help(); - int nCount; - int total = mnodeman.CountMasternodes(0); - if (deterministicMNManager->IsDIP3Active()) { - nCount = mnodeman.CountEnabled(); - } else { - masternode_info_t mnInfo; - mnodeman.GetNextMasternodeInQueueForPayment(true, nCount, mnInfo); - } - - int ps = mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION); - int enabled = mnodeman.CountEnabled(); + auto mnList = deterministicMNManager->GetListAtChainTip(); + int total = mnList.GetAllMNsCount(); + int enabled = mnList.GetValidMNsCount(); if (request.params.size() == 1) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("total", total)); - obj.push_back(Pair("ps_compatible", ps)); obj.push_back(Pair("enabled", enabled)); - obj.push_back(Pair("qualify", nCount)); return obj; } @@ -252,18 +242,12 @@ UniValue masternode_count(const JSONRPCRequest& request) if (strMode == "total") return total; - if (strMode == "ps") - return ps; - if (strMode == "enabled") return enabled; - if (strMode == "qualify") - return nCount; - if (strMode == "all") - return strprintf("Total: %d (PS Compatible: %d / Enabled: %d / Qualify: %d)", - total, ps, enabled, nCount); + return strprintf("Total: %d (Enabled: %d)", + total, enabled); throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown mode value"); } From adc2ec22530668641a429de8e60d77ecfa6d494e Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 13:20:16 +0100 Subject: [PATCH 20/26] Remove unsupported types/fields from "masternode list" --- src/rpc/masternode.cpp | 64 ++++++------------------------------------ 1 file changed, 9 insertions(+), 55 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index c7d2d85894..de5a6a76bb 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -136,26 +136,20 @@ void masternode_list_help() "2. \"filter\" (string, optional) Filter results. Partial match by outpoint by default in all modes,\n" " additional matches in some modes are also available\n" "\nAvailable modes:\n" - " activeseconds - Print number of seconds masternode recognized by the network as enabled\n" - " (since latest issued \"masternode start/start-many/start-alias\")\n" " addr - Print ip address associated with a masternode (can be additionally filtered, partial match)\n" - " daemon - Print daemon version of a masternode (can be additionally filtered, exact match)\n" - " full - Print info in format 'status protocol payee lastseen activeseconds lastpaidtime lastpaidblock IP'\n" + " full - Print info in format 'status payee lastpaidtime lastpaidblock IP'\n" " (can be additionally filtered, partial match)\n" - " info - Print info in format 'status protocol payee lastseen activeseconds sentinelversion sentinelstate IP'\n" + " info - Print info in format 'status payee IP'\n" " (can be additionally filtered, partial match)\n" " json - Print info in JSON format (can be additionally filtered, partial match)\n" " lastpaidblock - Print the last block height a node was paid on the network\n" " lastpaidtime - Print the last time a node was paid on the network\n" - " lastseen - Print timestamp of when a masternode was last seen on the network\n" " payee - Print Dash address associated with a masternode (can be additionally filtered,\n" " partial match)\n" - " protocol - Print protocol of a masternode (can be additionally filtered, exact match)\n" " keyid - Print the masternode (not collateral) key id\n" " rank - Print rank of a masternode based on current block\n" - " sentinel - Print sentinel version of a masternode (can be additionally filtered, exact match)\n" - " status - Print masternode status: PRE_ENABLED / ENABLED / EXPIRED / SENTINEL_PING_EXPIRED / NEW_START_REQUIRED /\n" - " UPDATE_REQUIRED / POSE_BAN / OUTPOINT_SPENT (can be additionally filtered, partial match)\n" + " status - Print masternode status: ENABED / POSE_BAN / OUTPOINT_SPENT\n" + " (can be additionally filtered, partial match)\n" ); } @@ -819,10 +813,10 @@ UniValue masternodelist(const JSONRPCRequest& request) if (request.params.size() == 2) strFilter = request.params[1].get_str(); if (request.fHelp || ( - strMode != "activeseconds" && strMode != "addr" && strMode != "daemon" && strMode != "full" && strMode != "info" && strMode != "json" && - strMode != "lastseen" && strMode != "lastpaidtime" && strMode != "lastpaidblock" && - strMode != "protocol" && strMode != "payee" && strMode != "pubkey" && - strMode != "rank" && strMode != "sentinel" && strMode != "status")) + strMode != "addr" && strMode != "full" && strMode != "info" && strMode != "json" && + strMode != "lastpaidtime" && strMode != "lastpaidblock" && + strMode != "payee" && strMode != "pubkey" && + strMode != "rank" && strMode != "status")) { masternode_list_help(); } @@ -867,32 +861,16 @@ UniValue masternodelist(const JSONRPCRequest& request) payeeStr = CBitcoinAddress(payeeDest).ToString(); } - if (strMode == "activeseconds") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, (int64_t)(mn.lastPing.sigTime - mn.sigTime))); - } else if (strMode == "addr") { + if (strMode == "addr") { std::string strAddress = mn.addr.ToString(); if (strFilter !="" && strAddress.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) continue; obj.push_back(Pair(strOutpoint, strAddress)); - } else if (strMode == "daemon") { - std::string strDaemon = mn.lastPing.GetDaemonString(); - if (strFilter !="" && strDaemon.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, strDaemon)); - } else if (strMode == "sentinel") { - std::string strSentinel = mn.lastPing.GetSentinelString(); - if (strFilter !="" && strSentinel.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, strSentinel)); } else if (strMode == "full") { std::ostringstream streamFull; streamFull << std::setw(18) << mn.GetStatus() << " " << - mn.nProtocolVersion << " " << payeeStr << " " << - (int64_t)mn.lastPing.sigTime << " " << std::setw(8) << - (int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " << std::setw(10) << mn.GetLastPaidTime() << " " << std::setw(6) << mn.GetLastPaidBlock() << " " << mn.addr.ToString(); @@ -904,12 +882,7 @@ UniValue masternodelist(const JSONRPCRequest& request) std::ostringstream streamInfo; streamInfo << std::setw(18) << mn.GetStatus() << " " << - mn.nProtocolVersion << " " << payeeStr << " " << - (int64_t)mn.lastPing.sigTime << " " << std::setw(8) << - (int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " << - mn.lastPing.GetSentinelString() << " " << - (mn.lastPing.fSentinelIsCurrent ? "current" : "expired") << " " << mn.addr.ToString(); std::string strInfo = streamInfo.str(); if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && @@ -920,12 +893,6 @@ UniValue masternodelist(const JSONRPCRequest& request) streamInfo << mn.addr.ToString() << " " << CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString() << " " << mn.GetStatus() << " " << - mn.nProtocolVersion << " " << - mn.lastPing.nDaemonVersion << " " << - mn.lastPing.GetSentinelString() << " " << - (mn.lastPing.fSentinelIsCurrent ? "current" : "expired") << " " << - (int64_t)mn.lastPing.sigTime << " " << - (int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " << mn.GetLastPaidTime() << " " << mn.GetLastPaidBlock(); std::string strInfo = streamInfo.str(); @@ -935,12 +902,6 @@ UniValue masternodelist(const JSONRPCRequest& request) objMN.push_back(Pair("address", mn.addr.ToString())); objMN.push_back(Pair("payee", CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString())); objMN.push_back(Pair("status", mn.GetStatus())); - objMN.push_back(Pair("protocol", mn.nProtocolVersion)); - objMN.push_back(Pair("daemonversion", mn.lastPing.GetDaemonString())); - objMN.push_back(Pair("sentinelversion", mn.lastPing.GetSentinelString())); - objMN.push_back(Pair("sentinelstate", (mn.lastPing.fSentinelIsCurrent ? "current" : "expired"))); - objMN.push_back(Pair("lastseen", (int64_t)mn.lastPing.sigTime)); - objMN.push_back(Pair("activeseconds", (int64_t)(mn.lastPing.sigTime - mn.sigTime))); objMN.push_back(Pair("lastpaidtime", mn.GetLastPaidTime())); objMN.push_back(Pair("lastpaidblock", mn.GetLastPaidBlock())); obj.push_back(Pair(strOutpoint, objMN)); @@ -950,17 +911,10 @@ UniValue masternodelist(const JSONRPCRequest& request) } else if (strMode == "lastpaidtime") { if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; obj.push_back(Pair(strOutpoint, mn.GetLastPaidTime())); - } else if (strMode == "lastseen") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, (int64_t)mn.lastPing.sigTime)); } else if (strMode == "payee") { if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) continue; obj.push_back(Pair(strOutpoint, payeeStr)); - } else if (strMode == "protocol") { - if (strFilter !="" && strFilter != strprintf("%d", mn.nProtocolVersion) && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, mn.nProtocolVersion)); } else if (strMode == "keyIDOwner") { if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOwner))); From 0fe97a0459eb3b3b68c7b7cb74c4fa7bcd8f06cc Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 16:02:12 +0100 Subject: [PATCH 21/26] Remove support for "masternode list rank" --- src/rpc/masternode.cpp | 185 ++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 97 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index de5a6a76bb..345429520d 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -816,7 +816,7 @@ UniValue masternodelist(const JSONRPCRequest& request) strMode != "addr" && strMode != "full" && strMode != "info" && strMode != "json" && strMode != "lastpaidtime" && strMode != "lastpaidblock" && strMode != "payee" && strMode != "pubkey" && - strMode != "rank" && strMode != "status")) + strMode != "status")) { masternode_list_help(); } @@ -831,107 +831,98 @@ UniValue masternodelist(const JSONRPCRequest& request) } UniValue obj(UniValue::VOBJ); - if (strMode == "rank") { - CMasternodeMan::rank_pair_vec_t vMasternodeRanks; - mnodeman.GetMasternodeRanks(vMasternodeRanks); - for (const auto& rankpair : vMasternodeRanks) { - std::string strOutpoint = rankpair.second.outpoint.ToStringShort(); - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, rankpair.first)); + std::map mapMasternodes = mnodeman.GetFullMasternodeMap(); + for (const auto& mnpair : mapMasternodes) { + CMasternode mn = mnpair.second; + std::string strOutpoint = mnpair.first.ToStringShort(); + + CScript payeeScript; + if (deterministicMNManager->IsDeterministicMNsSporkActive()) { + auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(mn.outpoint); + if (dmn) { + payeeScript = dmn->pdmnState->scriptPayout; + } + } else { + payeeScript = GetScriptForDestination(mn.keyIDCollateralAddress); } - } else { - std::map mapMasternodes = mnodeman.GetFullMasternodeMap(); - for (const auto& mnpair : mapMasternodes) { - CMasternode mn = mnpair.second; - std::string strOutpoint = mnpair.first.ToStringShort(); - CScript payeeScript; - if (deterministicMNManager->IsDIP3Active()) { - auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(mn.outpoint); - if (dmn) { - payeeScript = dmn->pdmnState->scriptPayout; - } - } else { - payeeScript = GetScriptForDestination(mn.keyIDCollateralAddress); - } + CTxDestination payeeDest; + std::string payeeStr = "UNKOWN"; + if (ExtractDestination(payeeScript, payeeDest)) { + payeeStr = CBitcoinAddress(payeeDest).ToString(); + } - CTxDestination payeeDest; - std::string payeeStr = "UNKOWN"; - if (ExtractDestination(payeeScript, payeeDest)) { - payeeStr = CBitcoinAddress(payeeDest).ToString(); - } - - if (strMode == "addr") { - std::string strAddress = mn.addr.ToString(); - if (strFilter !="" && strAddress.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, strAddress)); - } else if (strMode == "full") { - std::ostringstream streamFull; - streamFull << std::setw(18) << - mn.GetStatus() << " " << - payeeStr << " " << - mn.GetLastPaidTime() << " " << std::setw(6) << - mn.GetLastPaidBlock() << " " << - mn.addr.ToString(); - std::string strFull = streamFull.str(); - if (strFilter !="" && strFull.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, strFull)); - } else if (strMode == "info") { - std::ostringstream streamInfo; - streamInfo << std::setw(18) << - mn.GetStatus() << " " << - payeeStr << " " << - mn.addr.ToString(); - std::string strInfo = streamInfo.str(); - if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, strInfo)); - } else if (strMode == "json") { - std::ostringstream streamInfo; - streamInfo << mn.addr.ToString() << " " << - CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString() << " " << - mn.GetStatus() << " " << - mn.GetLastPaidTime() << " " << - mn.GetLastPaidBlock(); - std::string strInfo = streamInfo.str(); - if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - UniValue objMN(UniValue::VOBJ); - objMN.push_back(Pair("address", mn.addr.ToString())); - objMN.push_back(Pair("payee", CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString())); - objMN.push_back(Pair("status", mn.GetStatus())); - objMN.push_back(Pair("lastpaidtime", mn.GetLastPaidTime())); - objMN.push_back(Pair("lastpaidblock", mn.GetLastPaidBlock())); - obj.push_back(Pair(strOutpoint, objMN)); - } else if (strMode == "lastpaidblock") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, mn.GetLastPaidBlock())); - } else if (strMode == "lastpaidtime") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, mn.GetLastPaidTime())); - } else if (strMode == "payee") { - if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, payeeStr)); - } else if (strMode == "keyIDOwner") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOwner))); - } else if (strMode == "keyIDOperator") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, HexStr(mn.legacyKeyIDOperator))); - } else if (strMode == "keyIDVoting") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDVoting))); - } else if (strMode == "status") { - std::string strStatus = mn.GetStatus(); - if (strFilter !="" && strStatus.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, strStatus)); - } + if (strMode == "addr") { + std::string strAddress = mn.addr.ToString(); + if (strFilter !="" && strAddress.find(strFilter) == std::string::npos && + strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, strAddress)); + } else if (strMode == "full") { + std::ostringstream streamFull; + streamFull << std::setw(18) << + mn.GetStatus() << " " << + payeeStr << " " << + mn.GetLastPaidTime() << " " << std::setw(6) << + mn.GetLastPaidBlock() << " " << + mn.addr.ToString(); + std::string strFull = streamFull.str(); + if (strFilter !="" && strFull.find(strFilter) == std::string::npos && + strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, strFull)); + } else if (strMode == "info") { + std::ostringstream streamInfo; + streamInfo << std::setw(18) << + mn.GetStatus() << " " << + payeeStr << " " << + mn.addr.ToString(); + std::string strInfo = streamInfo.str(); + if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && + strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, strInfo)); + } else if (strMode == "json") { + std::ostringstream streamInfo; + streamInfo << mn.addr.ToString() << " " << + CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString() << " " << + mn.GetStatus() << " " << + mn.GetLastPaidTime() << " " << + mn.GetLastPaidBlock(); + std::string strInfo = streamInfo.str(); + if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && + strOutpoint.find(strFilter) == std::string::npos) continue; + UniValue objMN(UniValue::VOBJ); + objMN.push_back(Pair("address", mn.addr.ToString())); + objMN.push_back(Pair("payee", CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString())); + objMN.push_back(Pair("status", mn.GetStatus())); + objMN.push_back(Pair("lastpaidtime", mn.GetLastPaidTime())); + objMN.push_back(Pair("lastpaidblock", mn.GetLastPaidBlock())); + obj.push_back(Pair(strOutpoint, objMN)); + } else if (strMode == "lastpaidblock") { + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, mn.GetLastPaidBlock())); + } else if (strMode == "lastpaidtime") { + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, mn.GetLastPaidTime())); + } else if (strMode == "payee") { + if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos && + strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, payeeStr)); + } else if (strMode == "keyIDOwner") { + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOwner))); + } else if (strMode == "keyIDOperator") { + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, HexStr(mn.legacyKeyIDOperator))); + } else if (strMode == "keyIDVoting") { + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDVoting))); + } else if (strMode == "status") { + std::string strStatus = mn.GetStatus(); + if (strFilter !="" && strStatus.find(strFilter) == std::string::npos && + strOutpoint.find(strFilter) == std::string::npos) continue; + obj.push_back(Pair(strOutpoint, strStatus)); } } + return obj; } From 4c749b7e946c1b5e8b75e035546069f0b7fb5a05 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 17 Dec 2018 16:36:58 +0100 Subject: [PATCH 22/26] Directly use deterministicMNManager in "masternode list" Also remove GetFullMasternodeMap --- src/rpc/masternode.cpp | 106 ++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 48 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 345429520d..ed1ceaf2ed 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -831,21 +831,31 @@ UniValue masternodelist(const JSONRPCRequest& request) } UniValue obj(UniValue::VOBJ); - std::map mapMasternodes = mnodeman.GetFullMasternodeMap(); - for (const auto& mnpair : mapMasternodes) { - CMasternode mn = mnpair.second; - std::string strOutpoint = mnpair.first.ToStringShort(); - CScript payeeScript; - if (deterministicMNManager->IsDeterministicMNsSporkActive()) { - auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(mn.outpoint); - if (dmn) { - payeeScript = dmn->pdmnState->scriptPayout; - } - } else { - payeeScript = GetScriptForDestination(mn.keyIDCollateralAddress); + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto dmnToStatus = [&](const CDeterministicMNCPtr& dmn) { + if (mnList.IsMNValid(dmn)) { + return "ENABLED"; + } + if (mnList.IsMNPoSeBanned(dmn)) { + return "POSE_BANNED"; + } + return "UNKNOWN"; + }; + auto dmnToLastPaidTime = [&](const CDeterministicMNCPtr& dmn) { + if (dmn->pdmnState->nLastPaidHeight == 0) { + return (int)0; } + LOCK(cs_main); + const CBlockIndex* pindex = chainActive[dmn->pdmnState->nLastPaidHeight]; + return (int)pindex->nTime; + }; + + mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) { + std::string strOutpoint = dmn->collateralOutpoint.ToStringShort(); + + CScript payeeScript = dmn->pdmnState->scriptPayout; CTxDestination payeeDest; std::string payeeStr = "UNKOWN"; if (ExtractDestination(payeeScript, payeeDest)) { @@ -853,75 +863,75 @@ UniValue masternodelist(const JSONRPCRequest& request) } if (strMode == "addr") { - std::string strAddress = mn.addr.ToString(); + std::string strAddress = dmn->pdmnState->ToString(); if (strFilter !="" && strAddress.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; + strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, strAddress)); } else if (strMode == "full") { std::ostringstream streamFull; streamFull << std::setw(18) << - mn.GetStatus() << " " << + dmnToStatus(dmn) << " " << payeeStr << " " << - mn.GetLastPaidTime() << " " << std::setw(6) << - mn.GetLastPaidBlock() << " " << - mn.addr.ToString(); + dmnToLastPaidTime(dmn) << " " << std::setw(6) << + dmn->pdmnState->nLastPaidHeight << " " << + dmn->pdmnState->addr.ToString(); std::string strFull = streamFull.str(); if (strFilter !="" && strFull.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; + strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, strFull)); } else if (strMode == "info") { std::ostringstream streamInfo; streamInfo << std::setw(18) << - mn.GetStatus() << " " << + dmnToStatus(dmn) << " " << payeeStr << " " << - mn.addr.ToString(); + dmn->pdmnState->addr.ToString(); std::string strInfo = streamInfo.str(); if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; + strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, strInfo)); } else if (strMode == "json") { std::ostringstream streamInfo; - streamInfo << mn.addr.ToString() << " " << - CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString() << " " << - mn.GetStatus() << " " << - mn.GetLastPaidTime() << " " << - mn.GetLastPaidBlock(); + streamInfo << dmn->pdmnState->addr.ToString() << " " << + CBitcoinAddress(dmn->pdmnState->scriptPayout).ToString() << " " << + dmnToStatus(dmn) << " " << + dmnToLastPaidTime(dmn) << " " << + dmn->pdmnState->nLastPaidHeight; std::string strInfo = streamInfo.str(); if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; + strOutpoint.find(strFilter) == std::string::npos) return; UniValue objMN(UniValue::VOBJ); - objMN.push_back(Pair("address", mn.addr.ToString())); - objMN.push_back(Pair("payee", CBitcoinAddress(mn.pubKeyCollateralAddress.GetID()).ToString())); - objMN.push_back(Pair("status", mn.GetStatus())); - objMN.push_back(Pair("lastpaidtime", mn.GetLastPaidTime())); - objMN.push_back(Pair("lastpaidblock", mn.GetLastPaidBlock())); + objMN.push_back(Pair("address", dmn->pdmnState->addr.ToString())); + objMN.push_back(Pair("payee", CBitcoinAddress(dmn->pdmnState->scriptPayout).ToString())); + objMN.push_back(Pair("status", dmnToStatus(dmn))); + objMN.push_back(Pair("lastpaidtime", dmnToLastPaidTime(dmn))); + objMN.push_back(Pair("lastpaidblock", dmn->pdmnState->nLastPaidHeight)); obj.push_back(Pair(strOutpoint, objMN)); } else if (strMode == "lastpaidblock") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, mn.GetLastPaidBlock())); + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; + obj.push_back(Pair(strOutpoint, dmn->pdmnState->nLastPaidHeight)); } else if (strMode == "lastpaidtime") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, mn.GetLastPaidTime())); + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; + obj.push_back(Pair(strOutpoint, dmnToLastPaidTime(dmn))); } else if (strMode == "payee") { if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; + strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, payeeStr)); } else if (strMode == "keyIDOwner") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDOwner))); - } else if (strMode == "keyIDOperator") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, HexStr(mn.legacyKeyIDOperator))); + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; + obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDOwner))); + } else if (strMode == "pubKeyOperator") { + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; + obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.ToString())); } else if (strMode == "keyIDVoting") { - if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; - obj.push_back(Pair(strOutpoint, HexStr(mn.keyIDVoting))); + if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; + obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDVoting))); } else if (strMode == "status") { - std::string strStatus = mn.GetStatus(); + std::string strStatus = dmnToStatus(dmn); if (strFilter !="" && strStatus.find(strFilter) == std::string::npos && - strOutpoint.find(strFilter) == std::string::npos) continue; + strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, strStatus)); } - } + }); return obj; } From 1efd7735805961beb7cea522c2b4cb79f2de5a17 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 28 Dec 2018 08:12:53 +0100 Subject: [PATCH 23/26] Remove non-DIP3 code path in CMasternodePayments::IsScheduled This relies on mnInfo which is not present anymore as we directly use deterministicMNManager now. --- src/masternode-payments.cpp | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index 87ff0dcf8d..bbab429894 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -645,32 +645,12 @@ bool CMasternodePayments::IsScheduled(const CDeterministicMNCPtr& dmnIn, int nNo { LOCK(cs_mapMasternodeBlocks); - if (deterministicMNManager->IsDIP3Active()) { - auto projectedPayees = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(8); - for (const auto &dmn : projectedPayees) { - if (dmn->proTxHash == dmnIn->proTxHash) { - return true; - } - } - return false; - } - - if(!masternodeSync.IsMasternodeListSynced()) return false; - - CScript mnpayee; - mnpayee = GetScriptForDestination(mnInfo.keyIDCollateralAddress); - - for(int64_t h = nCachedBlockHeight; h <= nCachedBlockHeight + 8; h++){ - if(h == nNotBlockHeight) continue; - std::vector voutMasternodePayments; - if(GetBlockTxOuts(h, 0, voutMasternodePayments)) { - for (const auto& txout : voutMasternodePayments) { - if (txout.scriptPubKey == mnpayee) - return true; - } + auto projectedPayees = deterministicMNManager->GetListAtChainTip().GetProjectedMNPayees(8); + for (const auto &dmn : projectedPayees) { + if (dmn->proTxHash == dmnIn->proTxHash) { + return true; } } - return false; } From 536229d170e6e2d4b8758ed0e974c72b0ae61e91 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Mon, 31 Dec 2018 13:57:58 +0100 Subject: [PATCH 24/26] Apply suggestions from code review Co-Authored-By: codablock --- src/instantx.cpp | 1 - src/privatesend.cpp | 4 ---- src/rpc/masternode.cpp | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/instantx.cpp b/src/instantx.cpp index dbe7e848ea..408d3dbccf 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -1126,7 +1126,6 @@ bool CTxLockVote::CheckSignature() const bool CTxLockVote::Sign() { - std::string strError; uint256 hash = GetSignatureHash(); diff --git a/src/privatesend.cpp b/src/privatesend.cpp index 2f7e6f1222..da06c49ab9 100644 --- a/src/privatesend.cpp +++ b/src/privatesend.cpp @@ -50,7 +50,6 @@ bool CPrivateSendQueue::Sign() { if (!fMasternodeMode) return false; - std::string strError = ""; uint256 hash = GetSignatureHash(); CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); @@ -64,7 +63,6 @@ bool CPrivateSendQueue::Sign() bool CPrivateSendQueue::CheckSignature(const CBLSPublicKey& blsPubKey) const { - std::string strError = ""; uint256 hash = GetSignatureHash(); CBLSSignature sig; @@ -96,7 +94,6 @@ bool CPrivateSendBroadcastTx::Sign() { if (!fMasternodeMode) return false; - std::string strError = ""; uint256 hash = GetSignatureHash(); @@ -111,7 +108,6 @@ bool CPrivateSendBroadcastTx::Sign() bool CPrivateSendBroadcastTx::CheckSignature(const CBLSPublicKey& blsPubKey) const { - std::string strError = ""; uint256 hash = GetSignatureHash(); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index ed1ceaf2ed..162b81458b 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -148,7 +148,7 @@ void masternode_list_help() " partial match)\n" " keyid - Print the masternode (not collateral) key id\n" " rank - Print rank of a masternode based on current block\n" - " status - Print masternode status: ENABED / POSE_BAN / OUTPOINT_SPENT\n" + " status - Print masternode status: ENABLED / POSE_BAN / OUTPOINT_SPENT\n" " (can be additionally filtered, partial match)\n" ); } From e54f6b274a9cb8b8e226bfdf26d2b0881e91a997 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 31 Dec 2018 14:01:04 +0100 Subject: [PATCH 25/26] Use ban score of 10 for invalid DSQ sigs --- src/privatesend-client.cpp | 3 ++- src/privatesend-server.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/privatesend-client.cpp b/src/privatesend-client.cpp index 98590e8a78..5088cda586 100644 --- a/src/privatesend-client.cpp +++ b/src/privatesend-client.cpp @@ -66,7 +66,8 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& if (!dmn) return; if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) { - // TODO ban? + LOCK(cs_main); + Misbehaving(pfrom->id, 10); return; } diff --git a/src/privatesend-server.cpp b/src/privatesend-server.cpp index 51472a21ba..c30da8e420 100644 --- a/src/privatesend-server.cpp +++ b/src/privatesend-server.cpp @@ -10,6 +10,7 @@ #include "init.h" #include "masternode-sync.h" #include "masternodeman.h" +#include "net_processing.h" #include "netmessagemaker.h" #include "script/interpreter.h" #include "txmempool.h" @@ -118,7 +119,8 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (!dmn) return; if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) { - // TODO ban? + LOCK(cs_main); + Misbehaving(pfrom->id, 10); return; } From 78c22ad0fbd3f7858d0da4b0e9c720b90a382101 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 31 Dec 2018 14:05:23 +0100 Subject: [PATCH 26/26] Multiple fixes for "masternode list" 1. Make strMode lower case before comparing it (keyIDXXX would otherwise be case sensitive, leading to confusion for users) 2. Remove "rank" and "keyid" mode from help 3. Add keyIDOwner/keyIDVoting/pubKeyOperator to help and strMode check 4. Remove "pubkey" from strMode check 5. Call ToString() on address instead of whole DMN state 6. Add missing std::setw(10) to "full" mode --- src/rpc/masternode.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 162b81458b..9bf61955c5 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -142,12 +142,13 @@ void masternode_list_help() " info - Print info in format 'status payee IP'\n" " (can be additionally filtered, partial match)\n" " json - Print info in JSON format (can be additionally filtered, partial match)\n" + " keyIDOwner - Print the masternode owner key id\n" + " keyIDVoting - Print the masternode voting key id\n" " lastpaidblock - Print the last block height a node was paid on the network\n" " lastpaidtime - Print the last time a node was paid on the network\n" " payee - Print Dash address associated with a masternode (can be additionally filtered,\n" " partial match)\n" - " keyid - Print the masternode (not collateral) key id\n" - " rank - Print rank of a masternode based on current block\n" + " pubKeyOperator - Print the masternode operator public key\n" " status - Print masternode status: ENABLED / POSE_BAN / OUTPOINT_SPENT\n" " (can be additionally filtered, partial match)\n" ); @@ -812,10 +813,13 @@ UniValue masternodelist(const JSONRPCRequest& request) if (request.params.size() >= 1) strMode = request.params[0].get_str(); if (request.params.size() == 2) strFilter = request.params[1].get_str(); + std::transform(strMode.begin(), strMode.end(), strMode.begin(), ::tolower); + if (request.fHelp || ( strMode != "addr" && strMode != "full" && strMode != "info" && strMode != "json" && + strMode != "keyidowner" && strMode != "keyidvoting" && strMode != "lastpaidtime" && strMode != "lastpaidblock" && - strMode != "payee" && strMode != "pubkey" && + strMode != "payee" && strMode != "pubkeyoperator" && strMode != "status")) { masternode_list_help(); @@ -863,7 +867,7 @@ UniValue masternodelist(const JSONRPCRequest& request) } if (strMode == "addr") { - std::string strAddress = dmn->pdmnState->ToString(); + std::string strAddress = dmn->pdmnState->addr.ToString(false); if (strFilter !="" && strAddress.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, strAddress)); @@ -871,7 +875,7 @@ UniValue masternodelist(const JSONRPCRequest& request) std::ostringstream streamFull; streamFull << std::setw(18) << dmnToStatus(dmn) << " " << - payeeStr << " " << + payeeStr << " " << std::setw(10) << dmnToLastPaidTime(dmn) << " " << std::setw(6) << dmn->pdmnState->nLastPaidHeight << " " << dmn->pdmnState->addr.ToString(); @@ -916,13 +920,13 @@ UniValue masternodelist(const JSONRPCRequest& request) if (strFilter !="" && payeeStr.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, payeeStr)); - } else if (strMode == "keyIDOwner") { + } else if (strMode == "keyidowner") { if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDOwner))); - } else if (strMode == "pubKeyOperator") { + } else if (strMode == "pubkeyoperator") { if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.ToString())); - } else if (strMode == "keyIDVoting") { + } else if (strMode == "keyidvoting") { if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; obj.push_back(Pair(strOutpoint, HexStr(dmn->pdmnState->keyIDVoting))); } else if (strMode == "status") {