diff --git a/src/darksend.cpp b/src/darksend.cpp index 7f1b76dc02f04..6ee30bea34f65 100644 --- a/src/darksend.cpp +++ b/src/darksend.cpp @@ -90,8 +90,6 @@ void CDarksendPool::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataS } } else if(strCommand == NetMsgType::DSQUEUE) { - TRY_LOCK(cs_darksend, lockRecv); - if(!lockRecv) return; if(pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { LogPrint("privatesend", "DSQUEUE -- incompatible version! nVersion: %d\n", pfrom->nVersion); @@ -101,11 +99,14 @@ void CDarksendPool::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataS CDarksendQueue dsq; vRecv >> dsq; - // process every dsq only once - BOOST_FOREACH(CDarksendQueue q, vecDarksendQueue) { - if(q == dsq) { - // LogPrint("privatesend", "DSQUEUE -- %s seen\n", dsq.ToString()); - return; + { + LOCK(cs_darksend); + // process every dsq only once + BOOST_FOREACH(CDarksendQueue q, vecDarksendQueue) { + if(q == dsq) { + // LogPrint("privatesend", "DSQUEUE -- %s seen\n", dsq.ToString()); + return; + } } } @@ -135,11 +136,15 @@ void CDarksendPool::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataS SubmitDenominate(); } } else { - BOOST_FOREACH(CDarksendQueue q, vecDarksendQueue) { - if(q.vin == dsq.vin) { - // 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", pmn->addr.ToString()); - return; + + { + LOCK(cs_darksend); + BOOST_FOREACH(CDarksendQueue q, vecDarksendQueue) { + if(q.vin == dsq.vin) { + // 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", pmn->addr.ToString()); + return; + } } } @@ -724,6 +729,8 @@ void CDarksendPool::ChargeFees() LogPrintf("CDarksendPool::ChargeFees -- found uncooperative node (didn't %s transaction), charging fees: %s\n", (nState == POOL_STATE_SIGNING) ? "sign" : "send", vecOffendersCollaterals[0].ToString()); + LOCK(cs_main); + CValidationState state; bool fMissingInputs; if(!AcceptToMemoryPool(mempool, state, vecOffendersCollaterals[0], false, &fMissingInputs, false, true)) { @@ -751,6 +758,8 @@ void CDarksendPool::ChargeRandomFees() { if(!fMasterNode) return; + LOCK(cs_main); + BOOST_FOREACH(const CTransaction& txCollateral, vecSessionCollaterals) { if(GetRandInt(100) > 10) return; @@ -773,13 +782,17 @@ void CDarksendPool::ChargeRandomFees() // void CDarksendPool::CheckTimeout() { - // check mixing queue objects for timeouts - std::vector::iterator it = vecDarksendQueue.begin(); - while(it != vecDarksendQueue.end()) { - if((*it).IsExpired()) { - LogPrint("privatesend", "CDarksendPool::CheckTimeout -- Removing expired queue (%s)\n", (*it).ToString()); - it = vecDarksendQueue.erase(it); - } else ++it; + { + LOCK(cs_darksend); + + // check mixing queue objects for timeouts + std::vector::iterator it = vecDarksendQueue.begin(); + while(it != vecDarksendQueue.end()) { + if((*it).IsExpired()) { + LogPrint("privatesend", "CDarksendPool::CheckTimeout -- Removing expired queue (%s)\n", (*it).ToString()); + it = vecDarksendQueue.erase(it); + } else ++it; + } } if(!fEnablePrivateSend && !fMasterNode) return; @@ -1347,11 +1360,7 @@ bool CDarksendPool::DoAutomaticDenominating(bool fDryRun) return false; } - TRY_LOCK(cs_darksend, lockDS); - if(!lockDS) { - strAutoDenomResult = _("Lock is already in place."); - return false; - } + LOCK2(cs_main, cs_darksend); if(!fDryRun && pwalletMain->IsLocked(true)) { strAutoDenomResult = _("Wallet is locked."); @@ -2335,11 +2344,22 @@ bool CDarksendQueue::CheckSignature(const CPubKey& pubKeyMasternode) bool CDarksendQueue::Relay() { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + std::vector vNodesCopy; + { + LOCK(cs_vNodes); + vNodesCopy = vNodes; + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->AddRef(); + } + BOOST_FOREACH(CNode* pnode, vNodesCopy) if(pnode->nVersion >= MIN_PRIVATESEND_PEER_PROTO_VERSION) pnode->PushMessage(NetMsgType::DSQUEUE, (*this)); + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->Release(); + } return true; } @@ -2463,6 +2483,8 @@ void ThreadCheckDarkSendPool() if(nTick % MASTERNODE_MIN_MNP_SECONDS == 1) activeMasternode.ManageState(); + mnodeman.Check(); + if(nTick % 60 == 0) { mnodeman.CheckAndRemove(); mnodeman.ProcessMasternodeConnections(); diff --git a/src/governance.cpp b/src/governance.cpp index c69782bac55c1..6dec91bd72366 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -110,8 +110,6 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C if(pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) return; - LOCK(cs); - // ANOTHER USER IS ASKING US TO HELP THEM SYNC GOVERNANCE OBJECT DATA if (strCommand == NetMsgType::MNGOVERNANCESYNC) { @@ -164,6 +162,8 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C return; } + LOCK2(cs_main, cs); + if(mapSeenGovernanceObjects.count(nHash)) { // TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE? LogPrint("gobject", "CGovernanceManager -- Received already seen object: %s\n", strHash); diff --git a/src/instantx.cpp b/src/instantx.cpp index 68bd691736ee7..0b3f19ffedc88 100644 --- a/src/instantx.cpp +++ b/src/instantx.cpp @@ -72,9 +72,12 @@ bool IsInstantSendTxValid(const CTransaction& txCandidate) { if(txCandidate.vout.size() < 1) return false; - if(!CheckFinalTx(txCandidate)) { - LogPrint("instantsend", "IsInstantSendTxValid -- Transaction is not final: txCandidate=%s", txCandidate.ToString()); - return false; + { + LOCK(cs_main); + if(!CheckFinalTx(txCandidate)) { + LogPrint("instantsend", "IsInstantSendTxValid -- Transaction is not final: txCandidate=%s", txCandidate.ToString()); + return false; + } } int64_t nValueIn = 0; @@ -460,16 +463,16 @@ int64_t GetAverageMasternodeOrphanVoteTime() void CleanTxLockCandidates() { - LOCK(cs_instantsend); - - std::map::iterator it = mapTxLockCandidates.begin(); - int nHeight; { LOCK(cs_main); nHeight = chainActive.Height(); } + LOCK(cs_instantsend); + + std::map::iterator it = mapTxLockCandidates.begin(); + while(it != mapTxLockCandidates.end()) { CTxLockCandidate &txLockCandidate = it->second; if(nHeight > txLockCandidate.nExpirationBlock) { diff --git a/src/main.cpp b/src/main.cpp index 31fe8f6ab0c92..f4e61aff6b7f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5057,14 +5057,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam { // Send stream from relay memory bool pushed = false; + map::iterator mi; { LOCK(cs_mapRelay); - map::iterator mi = mapRelay.find(inv); + mi = mapRelay.find(inv); if (mi != mapRelay.end()) { - pfrom->PushMessage(inv.GetCommand(), (*mi).second); pushed = true; } } + if(pushed) + pfrom->PushMessage(inv.GetCommand(), (*mi).second); if (!pushed && inv.type == MSG_TX) { CTransaction tx; diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index 6436eb7c6bcb1..453ae15f260d7 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -416,7 +416,7 @@ bool CMasternodePayments::AddPaymentVote(const CMasternodePaymentVote& vote) uint256 blockHash = uint256(); if(!GetBlockHash(blockHash, vote.nBlockHeight - 101)) return false; - LOCK2(cs_mapMasternodePaymentVotes, cs_mapMasternodeBlocks); + LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes); if(mapMasternodePaymentVotes.count(vote.GetHash())) return false; @@ -573,7 +573,7 @@ void CMasternodePayments::CheckAndRemove() { if(!pCurrentBlockIndex) return; - LOCK2(cs_mapMasternodePaymentVotes, cs_mapMasternodeBlocks); + LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes); int nLimit = GetStorageLimit(); @@ -781,7 +781,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode) // Old nodes can't process this if(pnode->nVersion < 70202) return; - LOCK(cs_mapMasternodeBlocks); + LOCK2(cs_main, cs_mapMasternodeBlocks); std::vector vToFetch; std::map::iterator it = mapMasternodeBlocks.begin(); diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index 35a045d38922b..028b7f51307db 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -162,6 +162,13 @@ void CMasternodeSync::ClearFulfilledRequests() } } +void ReleaseNodes(const std::vector &vNodesCopy) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->Release(); +} + void CMasternodeSync::ProcessTick() { static int nTick = 0; @@ -210,15 +217,21 @@ void CMasternodeSync::ProcessTick() return; } - LOCK2(mnodeman.cs, cs_vNodes); - if(nRequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL || (nRequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS && IsBlockchainSynced())) { SwitchToNextAsset(); } - BOOST_FOREACH(CNode* pnode, vNodes) + std::vector vNodesCopy; + { + LOCK(cs_vNodes); + vNodesCopy = vNodes; + BOOST_FOREACH(CNode* pnode, vNodesCopy) + pnode->AddRef(); + } + + BOOST_FOREACH(CNode* pnode, vNodesCopy) { // QUICK MODE (REGTEST ONLY!) if(Params().NetworkIDString() == CBaseChainParams::REGTEST) @@ -236,6 +249,7 @@ void CMasternodeSync::ProcessTick() nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED; } nRequestedMasternodeAttempt++; + ReleaseNodes(vNodesCopy); return; } @@ -271,9 +285,11 @@ void CMasternodeSync::ProcessTick() LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName()); // there is no way we can continue without masternode list, fail here and try later Fail(); + ReleaseNodes(vNodesCopy); return; } SwitchToNextAsset(); + ReleaseNodes(vNodesCopy); return; } @@ -288,6 +304,7 @@ void CMasternodeSync::ProcessTick() if(nRequestedMasternodeAttempt > 1 && nMnCount > nMnCountEstimated) { LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- found enough data\n", nTick, nRequestedMasternodeAssets); SwitchToNextAsset(); + ReleaseNodes(vNodesCopy); return; } @@ -300,6 +317,7 @@ void CMasternodeSync::ProcessTick() mnodeman.DsegUpdate(pnode); + ReleaseNodes(vNodesCopy); return; //this will cause each peer to get one request each six seconds for the various assets we need } @@ -316,9 +334,11 @@ void CMasternodeSync::ProcessTick() LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName()); // probably not a good idea to proceed without winner list Fail(); + ReleaseNodes(vNodesCopy); return; } SwitchToNextAsset(); + ReleaseNodes(vNodesCopy); return; } @@ -328,6 +348,7 @@ void CMasternodeSync::ProcessTick() if(nRequestedMasternodeAttempt > 1 && mnpayments.IsEnoughData()) { LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- found enough data\n", nTick, nRequestedMasternodeAssets); SwitchToNextAsset(); + ReleaseNodes(vNodesCopy); return; } @@ -343,6 +364,7 @@ void CMasternodeSync::ProcessTick() // ask node for missing pieces only (old nodes will not be asked) mnpayments.RequestLowDataPaymentBlocks(pnode); + ReleaseNodes(vNodesCopy); return; //this will cause each peer to get one request each six seconds for the various assets we need } @@ -359,6 +381,7 @@ void CMasternodeSync::ProcessTick() // it's kind of ok to skip this for now, hopefully we'll catch up later? } SwitchToNextAsset(); + ReleaseNodes(vNodesCopy); return; } @@ -384,6 +407,7 @@ void CMasternodeSync::ProcessTick() pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, uint256()); //sync masternode votes + ReleaseNodes(vNodesCopy); return; //this will cause each peer to get one request each six seconds for the various assets we need } } diff --git a/src/masternode.cpp b/src/masternode.cpp index 196beaa1b7a3f..016f51149aa74 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -180,8 +180,7 @@ void CMasternode::Check(bool fForce) int nHeight = 0; if(!fUnitTest) { - TRY_LOCK(cs_main, lockMain); - if(!lockMain) return; + AssertLockHeld(cs_main); CCoins coins; if(!pcoinsTip->GetCoins(vin.prevout.hash, coins) || @@ -307,12 +306,10 @@ std::string CMasternode::GetStatus() const int CMasternode::GetCollateralAge() { - int nHeight; - { - TRY_LOCK(cs_main, lockMain); - if(!lockMain || !chainActive.Tip()) return -1; - nHeight = chainActive.Height(); - } + AssertLockHeld(cs_main); + + if(!chainActive.Tip()) return -1; + int nHeight = chainActive.Height(); if (nCacheCollateralBlock == 0) { int nInputAge = GetInputAge(vin); @@ -564,33 +561,25 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos) return false; } - { - TRY_LOCK(cs_main, lockMain); - if(!lockMain) { - // not mnb fault, let it to be checked again later - LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to aquire lock, addr=%s", addr.ToString()); - mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); - return false; - } + AssertLockHeld(cs_main); - CCoins coins; - if(!pcoinsTip->GetCoins(vin.prevout.hash, coins) || - (unsigned int)vin.prevout.n>=coins.vout.size() || - coins.vout[vin.prevout.n].IsNull()) { - LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort()); - return false; - } - if(coins.vout[vin.prevout.n].nValue != 1000 * COIN) { - LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", vin.prevout.ToStringShort()); - return false; - } - if(chainActive.Height() - coins.nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) { - LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=%s\n", - Params().GetConsensus().nMasternodeMinimumConfirmations, vin.prevout.ToStringShort()); - // maybe we miss few blocks, let this mnb to be checked again later - mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); - return false; - } + CCoins coins; + if(!pcoinsTip->GetCoins(vin.prevout.hash, coins) || + (unsigned int)vin.prevout.n>=coins.vout.size() || + coins.vout[vin.prevout.n].IsNull()) { + LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort()); + return false; + } + if(coins.vout[vin.prevout.n].nValue != 1000 * COIN) { + LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", vin.prevout.ToStringShort()); + return false; + } + if(chainActive.Height() - coins.nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) { + LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=%s\n", + Params().GetConsensus().nMasternodeMinimumConfirmations, vin.prevout.ToStringShort()); + // maybe we miss few blocks, let this mnb to be checked again later + mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); + return false; } LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n"); @@ -608,17 +597,15 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos) uint256 hashBlock = uint256(); CTransaction tx2; GetTransaction(vin.prevout.hash, tx2, Params().GetConsensus(), hashBlock, true); - { - LOCK(cs_main); - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) { - CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation - CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations - if(pConfIndex->GetBlockTime() > sigTime) { - LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n", - sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pConfIndex->GetBlockTime(), vin.prevout.ToStringShort(), addr.ToString()); - return false; - } + + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) { + CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation + CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations + if(pConfIndex->GetBlockTime() > sigTime) { + LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n", + sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pConfIndex->GetBlockTime(), vin.prevout.ToStringShort(), addr.ToString()); + return false; } } @@ -779,21 +766,19 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled, bool fSimp return false; } - { - LOCK(cs_main); - BlockMap::iterator mi = mapBlockIndex.find(blockHash); - if (mi == mapBlockIndex.end()) { - LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping is invalid, unknown block hash: masternode=%s blockHash=%s\n", vin.prevout.ToStringShort(), blockHash.ToString()); - // maybe we stuck or forked so we shouldn't ban this node, just fail to accept this ping - // TODO: or should we also request this block? - return false; - } - if ((*mi).second && (*mi).second->nHeight < chainActive.Height() - 24) { - LogPrintf("CMasternodePing::CheckAndUpdate -- Masternode ping is invalid, block hash is too old: masternode=%s blockHash=%s\n", vin.prevout.ToStringShort(), blockHash.ToString()); - // Do nothing here (no Masternode update, no mnping relay) - // Let this node to be visible but fail to accept mnping - return false; - } + AssertLockHeld(cs_main); + BlockMap::iterator mi = mapBlockIndex.find(blockHash); + if (mi == mapBlockIndex.end()) { + LogPrint("masternode", "CMasternodePing::CheckAndUpdate -- Masternode ping is invalid, unknown block hash: masternode=%s blockHash=%s\n", vin.prevout.ToStringShort(), blockHash.ToString()); + // maybe we stuck or forked so we shouldn't ban this node, just fail to accept this ping + // TODO: or should we also request this block? + return false; + } + if ((*mi).second && (*mi).second->nHeight < chainActive.Height() - 24) { + LogPrintf("CMasternodePing::CheckAndUpdate -- Masternode ping is invalid, block hash is too old: masternode=%s blockHash=%s\n", vin.prevout.ToStringShort(), blockHash.ToString()); + // Do nothing here (no Masternode update, no mnping relay) + // Let this node to be visible but fail to accept mnping + return false; } if (fSimpleCheck) { @@ -852,6 +837,7 @@ void CMasternodePing::Relay() void CMasternode::AddGovernanceVote(uint256 nGovernanceObjectHash) { + LOCK(cs); if(mapGovernanceObjectsVotedOn.count(nGovernanceObjectHash)) { mapGovernanceObjectsVotedOn[nGovernanceObjectHash]++; } else { @@ -861,6 +847,7 @@ void CMasternode::AddGovernanceVote(uint256 nGovernanceObjectHash) void CMasternode::RemoveGovernanceObject(uint256 nGovernanceObjectHash) { + LOCK(cs); std::map::iterator it = mapGovernanceObjectsVotedOn.find(nGovernanceObjectHash); if(it == mapGovernanceObjectsVotedOn.end()) { return; @@ -882,6 +869,8 @@ void CMasternode::UpdateWatchdogVoteTime() */ void CMasternode::FlagGovernanceItemsAsDirty() { + LOCK(cs); + std::map::iterator it = mapGovernanceObjectsVotedOn.begin(); while(it != mapGovernanceObjectsVotedOn.end()){ CGovernanceObject *pObj = governance.FindGovernanceObject((*it).first); diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index c5f3d4af0836a..2e51a79b3af37 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -158,7 +158,7 @@ void CMasternodeMan::AskForMN(CNode* pnode, const CTxIn &vin) void CMasternodeMan::Check() { - LOCK(cs); + LOCK2(cs_main, cs); LogPrint("masternode", "CMasternodeMan::Check nLastWatchdogVoteTime = %d, IsWatchdogActive() = %d\n", nLastWatchdogVoteTime, IsWatchdogActive()); @@ -320,7 +320,6 @@ int CMasternodeMan::CountEnabled(int nProtocolVersion) nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion; BOOST_FOREACH(CMasternode& mn, vMasternodes) { - mn.Check(); if(mn.nProtocolVersion < nProtocolVersion || !mn.IsEnabled()) continue; nCount++; } @@ -460,10 +459,19 @@ bool CMasternodeMan::Has(const CTxIn& vin) // // Deterministically select the oldest/best masternode to pay on the network // +CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCount) +{ + if(!pCurrentBlockIndex) { + nCount = 0; + return NULL; + } + return GetNextMasternodeInQueueForPayment(pCurrentBlockIndex->nHeight, fFilterSigTime, nCount); +} + CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount) { // Need LOCK2 here to ensure consistent locking order because the GetBlockHash call below locks cs_main - LOCK2(cs_main,cs); + LOCK2(cs_main, cs); CMasternode *pBestMasternode = NULL; std::vector > vecMasternodeLastPaid; @@ -475,7 +483,6 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight int nMnCount = CountEnabled(); BOOST_FOREACH(CMasternode &mn, vMasternodes) { - mn.Check(); if(!mn.IsValidForPayment()) continue; // //check protocol version @@ -510,7 +517,7 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight // -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely // -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2 // -- (chance per block * chances before IsScheduled will fire) - int nTenthNetwork = CountEnabled()/10; + int nTenthNetwork = nMnCount/10; int nCountTenth = 0; arith_uint256 nHighest = 0; BOOST_FOREACH (PAIRTYPE(int, CMasternode*)& s, vecMasternodeLastPaid){ @@ -581,7 +588,6 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int nBlockHeight, int nM // scan for winner BOOST_FOREACH(CMasternode& mn, vMasternodes) { if(mn.nProtocolVersion < nMinProtocol) continue; - mn.Check(); if(fOnlyActive) { if(!mn.IsEnabled()) continue; } @@ -618,8 +624,6 @@ std::vector > CMasternodeMan::GetMasternodeRanks(int // scan for winner BOOST_FOREACH(CMasternode& mn, vMasternodes) { - mn.Check(); - if(mn.nProtocolVersion < nMinProtocol || !mn.IsEnabled()) continue; int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false); @@ -654,10 +658,7 @@ CMasternode* CMasternodeMan::GetMasternodeByRank(int nRank, int nBlockHeight, in BOOST_FOREACH(CMasternode& mn, vMasternodes) { if(mn.nProtocolVersion < nMinProtocol) continue; - if(fOnlyActive) { - mn.Check(); - if(!mn.IsEnabled()) continue; - } + if(fOnlyActive && !mn.IsEnabled()) continue; int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false); @@ -700,7 +701,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData if (strCommand == NetMsgType::MNANNOUNCE) { //Masternode Broadcast { - LOCK(cs); + LOCK2(cs_main, cs); CMasternodeBroadcast mnb; vRecv >> mnb; @@ -726,7 +727,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s\n", mnp.vin.prevout.ToStringShort()); - LOCK(cs); + LOCK2(cs_main, cs); if(mapSeenMasternodePing.count(mnp.GetHash())) return; //seen mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp)); @@ -814,7 +815,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData } else if (strCommand == NetMsgType::MNVERIFY) { // Masternode Verify - LOCK(cs); + LOCK2(cs_main, cs); CMasternodeVerification mnv; vRecv >> mnv; @@ -840,7 +841,7 @@ void CMasternodeMan::DoFullVerificationStep() std::vector > vecMasternodeRanks = GetMasternodeRanks(pCurrentBlockIndex->nHeight - 1, MIN_POSE_PROTO_VERSION); - LOCK(cs); + LOCK2(cs_main, cs); int nCount = 0; int nCountMax = std::max(10, (int)vMasternodes.size() / 100); // verify at least 10 masternode at once but at most 1% of all known masternodes @@ -969,6 +970,9 @@ bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vectornHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false"); + // pCurrentBlockIndex->nHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false"); BOOST_FOREACH(CMasternode& mn, vMasternodes) { - mn.UpdateLastPaid(pindex, nMaxBlocksToScanBack); + mn.UpdateLastPaid(pCurrentBlockIndex, nMaxBlocksToScanBack); } // every time is like the first time if winners list is not synced @@ -1433,7 +1438,7 @@ void CMasternodeMan::RemoveGovernanceObject(uint256 nGovernanceObjectHash) void CMasternodeMan::CheckMasternode(const CTxIn& vin, bool fForce) { - LOCK(cs); + LOCK2(cs_main, cs); CMasternode* pMN = Find(vin); if(!pMN) { return; @@ -1443,7 +1448,7 @@ void CMasternodeMan::CheckMasternode(const CTxIn& vin, bool fForce) void CMasternodeMan::CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce) { - LOCK(cs); + LOCK2(cs_main, cs); CMasternode* pMN = Find(pubKeyMasternode); if(!pMN) { return; @@ -1508,7 +1513,7 @@ void CMasternodeMan::UpdatedBlockTip(const CBlockIndex *pindex) if(fMasterNode) { DoFullVerificationStep(); // normal wallet does not need to update this every block, doing update on rpc call should be enough - UpdateLastPaid(pindex); + UpdateLastPaid(); } } diff --git a/src/masternodeman.h b/src/masternodeman.h index 61c5c81448c40..e877e2ff1f41c 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -271,11 +271,13 @@ class CMasternodeMan /// Find an entry in the masternode list that is next to be paid CMasternode* GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount); + /// Same as above but use current block height + CMasternode* GetNextMasternodeInQueueForPayment(bool fFilterSigTime, int& nCount); /// Find a random entry CMasternode* FindRandomNotInVec(const std::vector &vecToExclude, int nProtocolVersion = -1); - std::vector GetFullMasternodeVector() { Check(); return vMasternodes; } + std::vector GetFullMasternodeVector() { return vMasternodes; } std::vector > GetMasternodeRanks(int nBlockHeight = -1, int nMinProtocol=0); int GetMasternodeRank(const CTxIn &vin, int nBlockHeight, int nMinProtocol=0, bool fOnlyActive=true); @@ -304,7 +306,7 @@ class CMasternodeMan /// Perform complete check and only then update list and maps bool CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, int& nDos); - void UpdateLastPaid(const CBlockIndex *pindex); + void UpdateLastPaid(); void CheckAndRebuildMasternodeIndex(); diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index e9121c192cd1f..2a69e50631426 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -74,7 +74,6 @@ 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.size())) .arg(QString::number((int)mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION))) diff --git a/src/rpcgovernance.cpp b/src/rpcgovernance.cpp index db6b900e79507..79be6cf8ac436 100644 --- a/src/rpcgovernance.cpp +++ b/src/rpcgovernance.cpp @@ -83,12 +83,6 @@ UniValue gobject(const UniValue& params, bool fHelp) // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS - CBlockIndex* pindex = NULL; - { - LOCK(cs_main); - pindex = chainActive.Tip(); - } - std::vector mnEntries; mnEntries = masternodeConfig.getEntries(); @@ -116,9 +110,12 @@ UniValue gobject(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Trigger and watchdog objects need not be prepared (however only masternodes can create them)"); } - std::string strError = ""; - if(!govobj.IsValidLocally(pindex, strError, false)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError); + { + LOCK(cs_main); + std::string strError = ""; + if(!govobj.IsValidLocally(chainActive.Tip(), strError, false)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError); + } CWalletTx wtx; if(!pwalletMain->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), false)) { @@ -160,12 +157,6 @@ UniValue gobject(const UniValue& params, bool fHelp) // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS - CBlockIndex* pindex = NULL; - { - LOCK(cs_main); - pindex = chainActive.Tip(); - } - uint256 txidFee; if(params.size() == 6) { @@ -211,9 +202,12 @@ UniValue gobject(const UniValue& params, bool fHelp) } } - std::string strError = ""; - if(!govobj.IsValidLocally(pindex, strError, true)) { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError); + { + LOCK(cs_main); + std::string strError = ""; + if(!govobj.IsValidLocally(chainActive.Tip(), strError, true)) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError); + } } // RELAY THIS OBJECT @@ -552,18 +546,13 @@ UniValue gobject(const UniValue& params, bool fHelp) // SETUP BLOCK INDEX VARIABLE / RESULTS VARIABLE - CBlockIndex* pindex = NULL; - { - LOCK(cs_main); - pindex = chainActive.Tip(); - } + LOCK2(cs_main, governance.cs); + CBlockIndex* pindex = chainActive.Tip(); UniValue objResult(UniValue::VOBJ); // GET MATCHING GOVERNANCE OBJECTS - LOCK(governance.cs); - std::vector objs = governance.GetAllNewerThan(nStartTime); governance.UpdateLastDiffTime(GetTime()); diff --git a/src/rpcmasternode.cpp b/src/rpcmasternode.cpp index 666bc78ab851e..2dc48ef92a432 100644 --- a/src/rpcmasternode.cpp +++ b/src/rpcmasternode.cpp @@ -167,9 +167,8 @@ UniValue masternode(const UniValue& params, bool fHelp) if (strMode == "enabled") return mnodeman.CountEnabled(); - LOCK(cs_main); int nCount; - mnodeman.GetNextMasternodeInQueueForPayment(chainActive.Height(), true, nCount); + mnodeman.GetNextMasternodeInQueueForPayment(true, nCount); if (strMode == "qualify") return nCount; @@ -184,14 +183,12 @@ UniValue masternode(const UniValue& params, bool fHelp) { int nCount; int nHeight; - CBlockIndex* pindex; CMasternode* winner = NULL; { LOCK(cs_main); nHeight = chainActive.Height() + (strCommand == "current" ? 1 : 10); - pindex = chainActive.Tip(); } - mnodeman.UpdateLastPaid(pindex); + mnodeman.UpdateLastPaid(); winner = mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount); if(!winner) return "unknown"; @@ -482,22 +479,12 @@ UniValue masternodelist(const UniValue& params, bool fHelp) } if (strMode == "full" || strMode == "lastpaidtime" || strMode == "lastpaidblock") { - CBlockIndex* pindex; - { - LOCK(cs_main); - pindex = chainActive.Tip(); - } - mnodeman.UpdateLastPaid(pindex); + mnodeman.UpdateLastPaid(); } UniValue obj(UniValue::VOBJ); if (strMode == "rank") { - int nHeight; - { - LOCK(cs_main); - nHeight = chainActive.Height(); - } - std::vector > vMasternodeRanks = mnodeman.GetMasternodeRanks(nHeight); + std::vector > vMasternodeRanks = mnodeman.GetMasternodeRanks(); BOOST_FOREACH(PAIRTYPE(int, CMasternode)& s, vMasternodeRanks) { std::string strOutpoint = s.second.vin.prevout.ToStringShort(); if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 38f0301230054..1fba05b736976 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2754,7 +2754,7 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount) { CAmount nTotal = 0; { - LOCK(cs_wallet); + LOCK2(cs_main, cs_wallet); for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second;