Fix (dead)locks (#1169)
* locks in PS * lock in governance * locks in IS * lock in ProcessGetData * locks in CMasternodeSync * centralize mnodeman.Check call * locks order in mnpayments * use current block chainTip when possible (less locks) * add missing lock in CountInputsWithAmount * fix deadlock RequestLowDataPaymentBlocks/IsTransactionValid * LOCK2 in CheckMnbAndUpdateMasternodeList, CheckAndUpdate, SendVerifyRequest * LOCK(cs) is not needed here * Decouple governance init actions from serialization Should fix this: ``` Assertion failed: lock governance.cs not held in governance-classes.cpp:117; locks held: cs_Shutdown init.cpp:200 (TRY) cs ./governance.h:195 cs governance.cpp:835 Abort trap: 6 ```
This commit is contained in:
parent
ecdc160119
commit
0600a6ce1a
@ -724,6 +724,8 @@ void CDarksendPool::ChargeFees()
|
|||||||
LogPrintf("CDarksendPool::ChargeFees -- found uncooperative node (didn't %s transaction), charging fees: %s\n",
|
LogPrintf("CDarksendPool::ChargeFees -- found uncooperative node (didn't %s transaction), charging fees: %s\n",
|
||||||
(nState == POOL_STATE_SIGNING) ? "sign" : "send", vecOffendersCollaterals[0].ToString());
|
(nState == POOL_STATE_SIGNING) ? "sign" : "send", vecOffendersCollaterals[0].ToString());
|
||||||
|
|
||||||
|
LOCK(cs_main);
|
||||||
|
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
bool fMissingInputs;
|
bool fMissingInputs;
|
||||||
if(!AcceptToMemoryPool(mempool, state, vecOffendersCollaterals[0], false, &fMissingInputs, false, true)) {
|
if(!AcceptToMemoryPool(mempool, state, vecOffendersCollaterals[0], false, &fMissingInputs, false, true)) {
|
||||||
@ -751,6 +753,8 @@ void CDarksendPool::ChargeRandomFees()
|
|||||||
{
|
{
|
||||||
if(!fMasterNode) return;
|
if(!fMasterNode) return;
|
||||||
|
|
||||||
|
LOCK(cs_main);
|
||||||
|
|
||||||
BOOST_FOREACH(const CTransaction& txCollateral, vecSessionCollaterals) {
|
BOOST_FOREACH(const CTransaction& txCollateral, vecSessionCollaterals) {
|
||||||
|
|
||||||
if(GetRandInt(100) > 10) return;
|
if(GetRandInt(100) > 10) return;
|
||||||
@ -773,6 +777,10 @@ void CDarksendPool::ChargeRandomFees()
|
|||||||
//
|
//
|
||||||
void CDarksendPool::CheckTimeout()
|
void CDarksendPool::CheckTimeout()
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
TRY_LOCK(cs_darksend, lockDS);
|
||||||
|
if(!lockDS) return; // it's ok to fail here, we run this quite frequently
|
||||||
|
|
||||||
// check mixing queue objects for timeouts
|
// check mixing queue objects for timeouts
|
||||||
std::vector<CDarksendQueue>::iterator it = vecDarksendQueue.begin();
|
std::vector<CDarksendQueue>::iterator it = vecDarksendQueue.begin();
|
||||||
while(it != vecDarksendQueue.end()) {
|
while(it != vecDarksendQueue.end()) {
|
||||||
@ -781,6 +789,7 @@ void CDarksendPool::CheckTimeout()
|
|||||||
it = vecDarksendQueue.erase(it);
|
it = vecDarksendQueue.erase(it);
|
||||||
} else ++it;
|
} else ++it;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!fEnablePrivateSend && !fMasterNode) return;
|
if(!fEnablePrivateSend && !fMasterNode) return;
|
||||||
|
|
||||||
@ -2335,11 +2344,22 @@ bool CDarksendQueue::CheckSignature(const CPubKey& pubKeyMasternode)
|
|||||||
|
|
||||||
bool CDarksendQueue::Relay()
|
bool CDarksendQueue::Relay()
|
||||||
{
|
{
|
||||||
|
std::vector<CNode*> vNodesCopy;
|
||||||
|
{
|
||||||
LOCK(cs_vNodes);
|
LOCK(cs_vNodes);
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
vNodesCopy = vNodes;
|
||||||
|
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||||
|
pnode->AddRef();
|
||||||
|
}
|
||||||
|
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||||
if(pnode->nVersion >= MIN_PRIVATESEND_PEER_PROTO_VERSION)
|
if(pnode->nVersion >= MIN_PRIVATESEND_PEER_PROTO_VERSION)
|
||||||
pnode->PushMessage(NetMsgType::DSQUEUE, (*this));
|
pnode->PushMessage(NetMsgType::DSQUEUE, (*this));
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs_vNodes);
|
||||||
|
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||||
|
pnode->Release();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2463,6 +2483,8 @@ void ThreadCheckDarkSendPool()
|
|||||||
if(nTick % MASTERNODE_MIN_MNP_SECONDS == 1)
|
if(nTick % MASTERNODE_MIN_MNP_SECONDS == 1)
|
||||||
activeMasternode.ManageState();
|
activeMasternode.ManageState();
|
||||||
|
|
||||||
|
mnodeman.Check();
|
||||||
|
|
||||||
if(nTick % 60 == 0) {
|
if(nTick % 60 == 0) {
|
||||||
mnodeman.CheckAndRemove();
|
mnodeman.CheckAndRemove();
|
||||||
mnodeman.ProcessMasternodeConnections();
|
mnodeman.ProcessMasternodeConnections();
|
||||||
|
@ -111,8 +111,6 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
|
|||||||
|
|
||||||
if(pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) return;
|
if(pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) return;
|
||||||
|
|
||||||
LOCK(cs);
|
|
||||||
|
|
||||||
// ANOTHER USER IS ASKING US TO HELP THEM SYNC GOVERNANCE OBJECT DATA
|
// ANOTHER USER IS ASKING US TO HELP THEM SYNC GOVERNANCE OBJECT DATA
|
||||||
if (strCommand == NetMsgType::MNGOVERNANCESYNC)
|
if (strCommand == NetMsgType::MNGOVERNANCESYNC)
|
||||||
{
|
{
|
||||||
@ -165,6 +163,8 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, std::string& strCommand, C
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOCK(cs);
|
||||||
|
|
||||||
if(mapSeenGovernanceObjects.count(nHash)) {
|
if(mapSeenGovernanceObjects.count(nHash)) {
|
||||||
// TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE?
|
// TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE?
|
||||||
LogPrint("gobject", "CGovernanceManager -- Received already seen object: %s\n", strHash);
|
LogPrint("gobject", "CGovernanceManager -- Received already seen object: %s\n", strHash);
|
||||||
@ -870,6 +870,14 @@ void CGovernanceManager::AddCachedTriggers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGovernanceManager::InitOnLoad()
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
RebuildIndexes();
|
||||||
|
AddCachedTriggers();
|
||||||
|
ClearSeen();
|
||||||
|
}
|
||||||
|
|
||||||
std::string CGovernanceManager::ToString() const
|
std::string CGovernanceManager::ToString() const
|
||||||
{
|
{
|
||||||
std::ostringstream info;
|
std::ostringstream info;
|
||||||
|
@ -218,10 +218,6 @@ public:
|
|||||||
Clear();
|
Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(ser_action.ForRead()) {
|
|
||||||
RebuildIndexes();
|
|
||||||
AddCachedTriggers();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdatedBlockTip(const CBlockIndex *pindex);
|
void UpdatedBlockTip(const CBlockIndex *pindex);
|
||||||
@ -258,6 +254,8 @@ public:
|
|||||||
return fRateChecksEnabled;
|
return fRateChecksEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitOnLoad();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RequestGovernanceObject(CNode* pfrom, const uint256& nHash);
|
void RequestGovernanceObject(CNode* pfrom, const uint256& nHash);
|
||||||
|
|
||||||
|
@ -1875,7 +1875,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
if(!flatdb3.Load(governance)) {
|
if(!flatdb3.Load(governance)) {
|
||||||
return InitError("Failed to load governance cache from governance.dat");
|
return InitError("Failed to load governance cache from governance.dat");
|
||||||
}
|
}
|
||||||
governance.ClearSeen();
|
governance.InitOnLoad();
|
||||||
|
|
||||||
uiInterface.InitMessage(_("Loading fullfiled requests cache..."));
|
uiInterface.InitMessage(_("Loading fullfiled requests cache..."));
|
||||||
CFlatDB<CNetFulfilledRequestManager> flatdb4("netfulfilled.dat", "magicFulfilledCache");
|
CFlatDB<CNetFulfilledRequestManager> flatdb4("netfulfilled.dat", "magicFulfilledCache");
|
||||||
|
@ -72,10 +72,13 @@ bool IsInstantSendTxValid(const CTransaction& txCandidate)
|
|||||||
{
|
{
|
||||||
if(txCandidate.vout.size() < 1) return false;
|
if(txCandidate.vout.size() < 1) return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
if(!CheckFinalTx(txCandidate)) {
|
if(!CheckFinalTx(txCandidate)) {
|
||||||
LogPrint("instantsend", "IsInstantSendTxValid -- Transaction is not final: txCandidate=%s", txCandidate.ToString());
|
LogPrint("instantsend", "IsInstantSendTxValid -- Transaction is not final: txCandidate=%s", txCandidate.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int64_t nValueIn = 0;
|
int64_t nValueIn = 0;
|
||||||
int64_t nValueOut = 0;
|
int64_t nValueOut = 0;
|
||||||
@ -460,16 +463,16 @@ int64_t GetAverageMasternodeOrphanVoteTime()
|
|||||||
|
|
||||||
void CleanTxLockCandidates()
|
void CleanTxLockCandidates()
|
||||||
{
|
{
|
||||||
LOCK(cs_instantsend);
|
|
||||||
|
|
||||||
std::map<uint256, CTxLockCandidate>::iterator it = mapTxLockCandidates.begin();
|
|
||||||
|
|
||||||
int nHeight;
|
int nHeight;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
nHeight = chainActive.Height();
|
nHeight = chainActive.Height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOCK(cs_instantsend);
|
||||||
|
|
||||||
|
std::map<uint256, CTxLockCandidate>::iterator it = mapTxLockCandidates.begin();
|
||||||
|
|
||||||
while(it != mapTxLockCandidates.end()) {
|
while(it != mapTxLockCandidates.end()) {
|
||||||
CTxLockCandidate &txLockCandidate = it->second;
|
CTxLockCandidate &txLockCandidate = it->second;
|
||||||
if(nHeight > txLockCandidate.nExpirationBlock) {
|
if(nHeight > txLockCandidate.nExpirationBlock) {
|
||||||
|
@ -5057,14 +5057,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
|
|||||||
{
|
{
|
||||||
// Send stream from relay memory
|
// Send stream from relay memory
|
||||||
bool pushed = false;
|
bool pushed = false;
|
||||||
|
map<CInv, CDataStream>::iterator mi;
|
||||||
{
|
{
|
||||||
LOCK(cs_mapRelay);
|
LOCK(cs_mapRelay);
|
||||||
map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
|
mi = mapRelay.find(inv);
|
||||||
if (mi != mapRelay.end()) {
|
if (mi != mapRelay.end()) {
|
||||||
pfrom->PushMessage(inv.GetCommand(), (*mi).second);
|
|
||||||
pushed = true;
|
pushed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(pushed)
|
||||||
|
pfrom->PushMessage(inv.GetCommand(), (*mi).second);
|
||||||
|
|
||||||
if (!pushed && inv.type == MSG_TX) {
|
if (!pushed && inv.type == MSG_TX) {
|
||||||
CTransaction tx;
|
CTransaction tx;
|
||||||
|
@ -416,7 +416,7 @@ bool CMasternodePayments::AddPaymentVote(const CMasternodePaymentVote& vote)
|
|||||||
uint256 blockHash = uint256();
|
uint256 blockHash = uint256();
|
||||||
if(!GetBlockHash(blockHash, vote.nBlockHeight - 101)) return false;
|
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;
|
if(mapMasternodePaymentVotes.count(vote.GetHash())) return false;
|
||||||
|
|
||||||
@ -573,7 +573,7 @@ void CMasternodePayments::CheckAndRemove()
|
|||||||
{
|
{
|
||||||
if(!pCurrentBlockIndex) return;
|
if(!pCurrentBlockIndex) return;
|
||||||
|
|
||||||
LOCK2(cs_mapMasternodePaymentVotes, cs_mapMasternodeBlocks);
|
LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes);
|
||||||
|
|
||||||
int nLimit = GetStorageLimit();
|
int nLimit = GetStorageLimit();
|
||||||
|
|
||||||
@ -781,7 +781,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode)
|
|||||||
// Old nodes can't process this
|
// Old nodes can't process this
|
||||||
if(pnode->nVersion < 70202) return;
|
if(pnode->nVersion < 70202) return;
|
||||||
|
|
||||||
LOCK(cs_mapMasternodeBlocks);
|
LOCK2(cs_main, cs_mapMasternodeBlocks);
|
||||||
|
|
||||||
std::vector<CInv> vToFetch;
|
std::vector<CInv> vToFetch;
|
||||||
std::map<int, CMasternodeBlockPayees>::iterator it = mapMasternodeBlocks.begin();
|
std::map<int, CMasternodeBlockPayees>::iterator it = mapMasternodeBlocks.begin();
|
||||||
|
@ -162,6 +162,13 @@ void CMasternodeSync::ClearFulfilledRequests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReleaseNodes(const std::vector<CNode*> &vNodesCopy)
|
||||||
|
{
|
||||||
|
LOCK(cs_vNodes);
|
||||||
|
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||||
|
pnode->Release();
|
||||||
|
}
|
||||||
|
|
||||||
void CMasternodeSync::ProcessTick()
|
void CMasternodeSync::ProcessTick()
|
||||||
{
|
{
|
||||||
static int nTick = 0;
|
static int nTick = 0;
|
||||||
@ -210,15 +217,21 @@ void CMasternodeSync::ProcessTick()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK2(mnodeman.cs, cs_vNodes);
|
|
||||||
|
|
||||||
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL ||
|
if(nRequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL ||
|
||||||
(nRequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS && IsBlockchainSynced()))
|
(nRequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS && IsBlockchainSynced()))
|
||||||
{
|
{
|
||||||
SwitchToNextAsset();
|
SwitchToNextAsset();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
std::vector<CNode*> vNodesCopy;
|
||||||
|
{
|
||||||
|
LOCK(cs_vNodes);
|
||||||
|
vNodesCopy = vNodes;
|
||||||
|
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||||
|
pnode->AddRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(CNode* pnode, vNodesCopy)
|
||||||
{
|
{
|
||||||
// QUICK MODE (REGTEST ONLY!)
|
// QUICK MODE (REGTEST ONLY!)
|
||||||
if(Params().NetworkIDString() == CBaseChainParams::REGTEST)
|
if(Params().NetworkIDString() == CBaseChainParams::REGTEST)
|
||||||
@ -236,6 +249,7 @@ void CMasternodeSync::ProcessTick()
|
|||||||
nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
|
nRequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
|
||||||
}
|
}
|
||||||
nRequestedMasternodeAttempt++;
|
nRequestedMasternodeAttempt++;
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,9 +285,11 @@ void CMasternodeSync::ProcessTick()
|
|||||||
LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName());
|
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
|
// there is no way we can continue without masternode list, fail here and try later
|
||||||
Fail();
|
Fail();
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SwitchToNextAsset();
|
SwitchToNextAsset();
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,6 +304,7 @@ void CMasternodeSync::ProcessTick()
|
|||||||
if(nRequestedMasternodeAttempt > 1 && nMnCount > nMnCountEstimated) {
|
if(nRequestedMasternodeAttempt > 1 && nMnCount > nMnCountEstimated) {
|
||||||
LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- found enough data\n", nTick, nRequestedMasternodeAssets);
|
LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- found enough data\n", nTick, nRequestedMasternodeAssets);
|
||||||
SwitchToNextAsset();
|
SwitchToNextAsset();
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,6 +317,7 @@ void CMasternodeSync::ProcessTick()
|
|||||||
|
|
||||||
mnodeman.DsegUpdate(pnode);
|
mnodeman.DsegUpdate(pnode);
|
||||||
|
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return; //this will cause each peer to get one request each six seconds for the various assets we need
|
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());
|
LogPrintf("CMasternodeSync::ProcessTick -- ERROR: failed to sync %s\n", GetAssetName());
|
||||||
// probably not a good idea to proceed without winner list
|
// probably not a good idea to proceed without winner list
|
||||||
Fail();
|
Fail();
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SwitchToNextAsset();
|
SwitchToNextAsset();
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,6 +348,7 @@ void CMasternodeSync::ProcessTick()
|
|||||||
if(nRequestedMasternodeAttempt > 1 && mnpayments.IsEnoughData()) {
|
if(nRequestedMasternodeAttempt > 1 && mnpayments.IsEnoughData()) {
|
||||||
LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- found enough data\n", nTick, nRequestedMasternodeAssets);
|
LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nRequestedMasternodeAssets %d -- found enough data\n", nTick, nRequestedMasternodeAssets);
|
||||||
SwitchToNextAsset();
|
SwitchToNextAsset();
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +364,7 @@ void CMasternodeSync::ProcessTick()
|
|||||||
// ask node for missing pieces only (old nodes will not be asked)
|
// ask node for missing pieces only (old nodes will not be asked)
|
||||||
mnpayments.RequestLowDataPaymentBlocks(pnode);
|
mnpayments.RequestLowDataPaymentBlocks(pnode);
|
||||||
|
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return; //this will cause each peer to get one request each six seconds for the various assets we need
|
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?
|
// it's kind of ok to skip this for now, hopefully we'll catch up later?
|
||||||
}
|
}
|
||||||
SwitchToNextAsset();
|
SwitchToNextAsset();
|
||||||
|
ReleaseNodes(vNodesCopy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,6 +407,7 @@ void CMasternodeSync::ProcessTick()
|
|||||||
|
|
||||||
pnode->PushMessage(NetMsgType::MNGOVERNANCESYNC, uint256()); //sync masternode votes
|
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
|
return; //this will cause each peer to get one request each six seconds for the various assets we need
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,6 @@ int CMasternodeMan::CountEnabled(int nProtocolVersion)
|
|||||||
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
|
nProtocolVersion = nProtocolVersion == -1 ? mnpayments.GetMinMasternodePaymentsProto() : nProtocolVersion;
|
||||||
|
|
||||||
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
||||||
mn.Check();
|
|
||||||
if(mn.nProtocolVersion < nProtocolVersion || !mn.IsEnabled()) continue;
|
if(mn.nProtocolVersion < nProtocolVersion || !mn.IsEnabled()) continue;
|
||||||
nCount++;
|
nCount++;
|
||||||
}
|
}
|
||||||
@ -460,6 +459,15 @@ bool CMasternodeMan::Has(const CTxIn& vin)
|
|||||||
//
|
//
|
||||||
// Deterministically select the oldest/best masternode to pay on the network
|
// 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)
|
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
|
// Need LOCK2 here to ensure consistent locking order because the GetBlockHash call below locks cs_main
|
||||||
@ -475,7 +483,6 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
|
|||||||
int nMnCount = CountEnabled();
|
int nMnCount = CountEnabled();
|
||||||
BOOST_FOREACH(CMasternode &mn, vMasternodes)
|
BOOST_FOREACH(CMasternode &mn, vMasternodes)
|
||||||
{
|
{
|
||||||
mn.Check();
|
|
||||||
if(!mn.IsValidForPayment()) continue;
|
if(!mn.IsValidForPayment()) continue;
|
||||||
|
|
||||||
// //check protocol version
|
// //check protocol version
|
||||||
@ -581,7 +588,6 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int nBlockHeight, int nM
|
|||||||
// scan for winner
|
// scan for winner
|
||||||
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
||||||
if(mn.nProtocolVersion < nMinProtocol) continue;
|
if(mn.nProtocolVersion < nMinProtocol) continue;
|
||||||
mn.Check();
|
|
||||||
if(fOnlyActive) {
|
if(fOnlyActive) {
|
||||||
if(!mn.IsEnabled()) continue;
|
if(!mn.IsEnabled()) continue;
|
||||||
}
|
}
|
||||||
@ -618,8 +624,6 @@ std::vector<std::pair<int, CMasternode> > CMasternodeMan::GetMasternodeRanks(int
|
|||||||
// scan for winner
|
// scan for winner
|
||||||
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
||||||
|
|
||||||
mn.Check();
|
|
||||||
|
|
||||||
if(mn.nProtocolVersion < nMinProtocol || !mn.IsEnabled()) continue;
|
if(mn.nProtocolVersion < nMinProtocol || !mn.IsEnabled()) continue;
|
||||||
|
|
||||||
int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false);
|
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) {
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
||||||
|
|
||||||
if(mn.nProtocolVersion < nMinProtocol) continue;
|
if(mn.nProtocolVersion < nMinProtocol) continue;
|
||||||
if(fOnlyActive) {
|
if(fOnlyActive && !mn.IsEnabled()) continue;
|
||||||
mn.Check();
|
|
||||||
if(!mn.IsEnabled()) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false);
|
int64_t nScore = mn.CalculateScore(blockHash).GetCompact(false);
|
||||||
|
|
||||||
@ -699,9 +700,6 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
|||||||
|
|
||||||
if (strCommand == NetMsgType::MNANNOUNCE) { //Masternode Broadcast
|
if (strCommand == NetMsgType::MNANNOUNCE) { //Masternode Broadcast
|
||||||
|
|
||||||
{
|
|
||||||
LOCK(cs);
|
|
||||||
|
|
||||||
CMasternodeBroadcast mnb;
|
CMasternodeBroadcast mnb;
|
||||||
vRecv >> mnb;
|
vRecv >> mnb;
|
||||||
|
|
||||||
@ -713,7 +711,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
|||||||
} else if(nDos > 0) {
|
} else if(nDos > 0) {
|
||||||
Misbehaving(pfrom->GetId(), nDos);
|
Misbehaving(pfrom->GetId(), nDos);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(fMasternodesAdded) {
|
if(fMasternodesAdded) {
|
||||||
NotifyMasternodeUpdates();
|
NotifyMasternodeUpdates();
|
||||||
}
|
}
|
||||||
@ -726,7 +724,8 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
|||||||
|
|
||||||
LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s\n", mnp.vin.prevout.ToStringShort());
|
LogPrint("masternode", "MNPING -- Masternode ping, masternode=%s\n", mnp.vin.prevout.ToStringShort());
|
||||||
|
|
||||||
LOCK(cs);
|
// Need LOCK2 here to ensure consistent locking order because the CheckAndUpdate call below locks cs_main
|
||||||
|
LOCK2(cs_main, cs);
|
||||||
|
|
||||||
if(mapSeenMasternodePing.count(mnp.GetHash())) return; //seen
|
if(mapSeenMasternodePing.count(mnp.GetHash())) return; //seen
|
||||||
mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
|
mapSeenMasternodePing.insert(std::make_pair(mnp.GetHash(), mnp));
|
||||||
@ -840,7 +839,9 @@ void CMasternodeMan::DoFullVerificationStep()
|
|||||||
|
|
||||||
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks = GetMasternodeRanks(pCurrentBlockIndex->nHeight - 1, MIN_POSE_PROTO_VERSION);
|
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks = GetMasternodeRanks(pCurrentBlockIndex->nHeight - 1, MIN_POSE_PROTO_VERSION);
|
||||||
|
|
||||||
LOCK(cs);
|
// Need LOCK2 here to ensure consistent locking order because the SendVerifyRequest call below locks cs_main
|
||||||
|
// through GetHeight() signal in ConnectNode
|
||||||
|
LOCK2(cs_main, cs);
|
||||||
|
|
||||||
int nCount = 0;
|
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
|
int nCountMax = std::max(10, (int)vMasternodes.size() / 100); // verify at least 10 masternode at once but at most 1% of all known masternodes
|
||||||
@ -1294,7 +1295,8 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb)
|
|||||||
|
|
||||||
bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, int& nDos)
|
bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, int& nDos)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
// Need LOCK2 here to ensure consistent locking order because the SimpleCheck call below locks cs_main
|
||||||
|
LOCK2(cs_main, cs);
|
||||||
|
|
||||||
nDos = 0;
|
nDos = 0;
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
||||||
@ -1347,11 +1349,12 @@ bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, i
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMasternodeMan::UpdateLastPaid(const CBlockIndex *pindex)
|
void CMasternodeMan::UpdateLastPaid()
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
||||||
if(fLiteMode) return;
|
if(fLiteMode) return;
|
||||||
|
if(!pCurrentBlockIndex) return;
|
||||||
|
|
||||||
static bool IsFirstRun = true;
|
static bool IsFirstRun = true;
|
||||||
// Do full scan on first run or if we are not a masternode
|
// Do full scan on first run or if we are not a masternode
|
||||||
@ -1359,10 +1362,10 @@ void CMasternodeMan::UpdateLastPaid(const CBlockIndex *pindex)
|
|||||||
int nMaxBlocksToScanBack = (IsFirstRun || !fMasterNode) ? mnpayments.GetStorageLimit() : LAST_PAID_SCAN_BLOCKS;
|
int nMaxBlocksToScanBack = (IsFirstRun || !fMasterNode) ? mnpayments.GetStorageLimit() : LAST_PAID_SCAN_BLOCKS;
|
||||||
|
|
||||||
// LogPrint("mnpayments", "CMasternodeMan::UpdateLastPaid -- nHeight=%d, nMaxBlocksToScanBack=%d, IsFirstRun=%s\n",
|
// LogPrint("mnpayments", "CMasternodeMan::UpdateLastPaid -- nHeight=%d, nMaxBlocksToScanBack=%d, IsFirstRun=%s\n",
|
||||||
// pindex->nHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false");
|
// pCurrentBlockIndex->nHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false");
|
||||||
|
|
||||||
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
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
|
// every time is like the first time if winners list is not synced
|
||||||
@ -1508,7 +1511,7 @@ void CMasternodeMan::UpdatedBlockTip(const CBlockIndex *pindex)
|
|||||||
if(fMasterNode) {
|
if(fMasterNode) {
|
||||||
DoFullVerificationStep();
|
DoFullVerificationStep();
|
||||||
// normal wallet does not need to update this every block, doing update on rpc call should be enough
|
// normal wallet does not need to update this every block, doing update on rpc call should be enough
|
||||||
UpdateLastPaid(pindex);
|
UpdateLastPaid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,11 +271,13 @@ public:
|
|||||||
|
|
||||||
/// Find an entry in the masternode list that is next to be paid
|
/// Find an entry in the masternode list that is next to be paid
|
||||||
CMasternode* GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount);
|
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
|
/// Find a random entry
|
||||||
CMasternode* FindRandomNotInVec(const std::vector<CTxIn> &vecToExclude, int nProtocolVersion = -1);
|
CMasternode* FindRandomNotInVec(const std::vector<CTxIn> &vecToExclude, int nProtocolVersion = -1);
|
||||||
|
|
||||||
std::vector<CMasternode> GetFullMasternodeVector() { Check(); return vMasternodes; }
|
std::vector<CMasternode> GetFullMasternodeVector() { return vMasternodes; }
|
||||||
|
|
||||||
std::vector<std::pair<int, CMasternode> > GetMasternodeRanks(int nBlockHeight = -1, int nMinProtocol=0);
|
std::vector<std::pair<int, CMasternode> > GetMasternodeRanks(int nBlockHeight = -1, int nMinProtocol=0);
|
||||||
int GetMasternodeRank(const CTxIn &vin, int nBlockHeight, int nMinProtocol=0, bool fOnlyActive=true);
|
int GetMasternodeRank(const CTxIn &vin, int nBlockHeight, int nMinProtocol=0, bool fOnlyActive=true);
|
||||||
@ -304,7 +306,7 @@ public:
|
|||||||
/// Perform complete check and only then update list and maps
|
/// Perform complete check and only then update list and maps
|
||||||
bool CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, int& nDos);
|
bool CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, int& nDos);
|
||||||
|
|
||||||
void UpdateLastPaid(const CBlockIndex *pindex);
|
void UpdateLastPaid();
|
||||||
|
|
||||||
void CheckAndRebuildMasternodeIndex();
|
void CheckAndRebuildMasternodeIndex();
|
||||||
|
|
||||||
|
@ -167,9 +167,8 @@ UniValue masternode(const UniValue& params, bool fHelp)
|
|||||||
if (strMode == "enabled")
|
if (strMode == "enabled")
|
||||||
return mnodeman.CountEnabled();
|
return mnodeman.CountEnabled();
|
||||||
|
|
||||||
LOCK(cs_main);
|
|
||||||
int nCount;
|
int nCount;
|
||||||
mnodeman.GetNextMasternodeInQueueForPayment(chainActive.Height(), true, nCount);
|
mnodeman.GetNextMasternodeInQueueForPayment(true, nCount);
|
||||||
|
|
||||||
if (strMode == "qualify")
|
if (strMode == "qualify")
|
||||||
return nCount;
|
return nCount;
|
||||||
@ -184,14 +183,12 @@ UniValue masternode(const UniValue& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
int nCount;
|
int nCount;
|
||||||
int nHeight;
|
int nHeight;
|
||||||
CBlockIndex* pindex;
|
|
||||||
CMasternode* winner = NULL;
|
CMasternode* winner = NULL;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
nHeight = chainActive.Height() + (strCommand == "current" ? 1 : 10);
|
nHeight = chainActive.Height() + (strCommand == "current" ? 1 : 10);
|
||||||
pindex = chainActive.Tip();
|
|
||||||
}
|
}
|
||||||
mnodeman.UpdateLastPaid(pindex);
|
mnodeman.UpdateLastPaid();
|
||||||
winner = mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount);
|
winner = mnodeman.GetNextMasternodeInQueueForPayment(nHeight, true, nCount);
|
||||||
if(!winner) return "unknown";
|
if(!winner) return "unknown";
|
||||||
|
|
||||||
@ -482,22 +479,12 @@ UniValue masternodelist(const UniValue& params, bool fHelp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strMode == "full" || strMode == "lastpaidtime" || strMode == "lastpaidblock") {
|
if (strMode == "full" || strMode == "lastpaidtime" || strMode == "lastpaidblock") {
|
||||||
CBlockIndex* pindex;
|
mnodeman.UpdateLastPaid();
|
||||||
{
|
|
||||||
LOCK(cs_main);
|
|
||||||
pindex = chainActive.Tip();
|
|
||||||
}
|
|
||||||
mnodeman.UpdateLastPaid(pindex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
if (strMode == "rank") {
|
if (strMode == "rank") {
|
||||||
int nHeight;
|
std::vector<std::pair<int, CMasternode> > vMasternodeRanks = mnodeman.GetMasternodeRanks();
|
||||||
{
|
|
||||||
LOCK(cs_main);
|
|
||||||
nHeight = chainActive.Height();
|
|
||||||
}
|
|
||||||
std::vector<std::pair<int, CMasternode> > vMasternodeRanks = mnodeman.GetMasternodeRanks(nHeight);
|
|
||||||
BOOST_FOREACH(PAIRTYPE(int, CMasternode)& s, vMasternodeRanks) {
|
BOOST_FOREACH(PAIRTYPE(int, CMasternode)& s, vMasternodeRanks) {
|
||||||
std::string strOutpoint = s.second.vin.prevout.ToStringShort();
|
std::string strOutpoint = s.second.vin.prevout.ToStringShort();
|
||||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||||
|
@ -2754,7 +2754,7 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount)
|
|||||||
{
|
{
|
||||||
CAmount nTotal = 0;
|
CAmount nTotal = 0;
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
|
||||||
{
|
{
|
||||||
const CWalletTx* pcoin = &(*it).second;
|
const CWalletTx* pcoin = &(*it).second;
|
||||||
|
Loading…
Reference in New Issue
Block a user