fix potential deadlock in CMasternodeMan::CheckMnbAndUpdateMasternodeList (#1543)
governance.cs -> mnodeman.cs: CGovernanceManager::ProcessMessage - LOCK2(cs_main, governance.cs) -> AddGovernanceObject -> UpdateSentinelVariables -> CountEnabled - LOCK(mnodeman.cs) mnodeman.cs -> governance.cs: CheckMnbAndUpdateMasternodeList - LOCK2(cs_main, mnodeman.cs) -> activeMasternode.ManageState -> ManageStateLocal -> NotifyMasternodeUpdates -> СheckMasternodeOrphanObjects - LOCK2(cs_main, governance.cs) ... -> NotifyMasternodeUpdates -> CheckMasternodeOrphanVotes - LOCK2(cs_main, governance.cs) ... -> NotifyMasternodeUpdates -> UpdateCachesAndClean - LOCK2(cs_main, governance.cs)
This commit is contained in:
parent
1c4e2946af
commit
4942884c71
@ -1405,90 +1405,94 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb)
|
|||||||
|
|
||||||
bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBroadcast mnb, int& nDos)
|
bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CNode* pfrom, CMasternodeBroadcast mnb, int& nDos)
|
||||||
{
|
{
|
||||||
// Need LOCK2 here to ensure consistent locking order because the SimpleCheck call below locks cs_main
|
// Need to lock cs_main here to ensure consistent locking order because the SimpleCheck call below locks cs_main
|
||||||
LOCK2(cs_main, cs);
|
LOCK(cs_main);
|
||||||
|
|
||||||
nDos = 0;
|
{
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
LOCK(cs);
|
||||||
|
nDos = 0;
|
||||||
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
||||||
|
|
||||||
uint256 hash = mnb.GetHash();
|
uint256 hash = mnb.GetHash();
|
||||||
if(mapSeenMasternodeBroadcast.count(hash) && !mnb.fRecovery) { //seen
|
if(mapSeenMasternodeBroadcast.count(hash) && !mnb.fRecovery) { //seen
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen\n", mnb.vin.prevout.ToStringShort());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen\n", mnb.vin.prevout.ToStringShort());
|
||||||
// less then 2 pings left before this MN goes into non-recoverable state, bump sync timeout
|
// less then 2 pings left before this MN goes into non-recoverable state, bump sync timeout
|
||||||
if(GetTime() - mapSeenMasternodeBroadcast[hash].first > MASTERNODE_NEW_START_REQUIRED_SECONDS - MASTERNODE_MIN_MNP_SECONDS * 2) {
|
if(GetTime() - mapSeenMasternodeBroadcast[hash].first > MASTERNODE_NEW_START_REQUIRED_SECONDS - MASTERNODE_MIN_MNP_SECONDS * 2) {
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen update\n", mnb.vin.prevout.ToStringShort());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen update\n", mnb.vin.prevout.ToStringShort());
|
||||||
mapSeenMasternodeBroadcast[hash].first = GetTime();
|
mapSeenMasternodeBroadcast[hash].first = GetTime();
|
||||||
masternodeSync.AddedMasternodeList();
|
masternodeSync.AddedMasternodeList();
|
||||||
}
|
}
|
||||||
// did we ask this node for it?
|
// did we ask this node for it?
|
||||||
if(pfrom && IsMnbRecoveryRequested(hash) && GetTime() < mMnbRecoveryRequests[hash].first) {
|
if(pfrom && IsMnbRecoveryRequested(hash) && GetTime() < mMnbRecoveryRequests[hash].first) {
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request\n", hash.ToString());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request\n", hash.ToString());
|
||||||
if(mMnbRecoveryRequests[hash].second.count(pfrom->addr)) {
|
if(mMnbRecoveryRequests[hash].second.count(pfrom->addr)) {
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s\n", hash.ToString(), pfrom->addr.ToString());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s\n", hash.ToString(), pfrom->addr.ToString());
|
||||||
// do not allow node to send same mnb multiple times in recovery mode
|
// do not allow node to send same mnb multiple times in recovery mode
|
||||||
mMnbRecoveryRequests[hash].second.erase(pfrom->addr);
|
mMnbRecoveryRequests[hash].second.erase(pfrom->addr);
|
||||||
// does it have newer lastPing?
|
// does it have newer lastPing?
|
||||||
if(mnb.lastPing.sigTime > mapSeenMasternodeBroadcast[hash].second.lastPing.sigTime) {
|
if(mnb.lastPing.sigTime > mapSeenMasternodeBroadcast[hash].second.lastPing.sigTime) {
|
||||||
// simulate Check
|
// simulate Check
|
||||||
CMasternode mnTemp = CMasternode(mnb);
|
CMasternode mnTemp = CMasternode(mnb);
|
||||||
mnTemp.Check();
|
mnTemp.Check();
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s, better lastPing: %d min ago, projected mn state: %s\n", hash.ToString(), pfrom->addr.ToString(), (GetTime() - mnb.lastPing.sigTime)/60, mnTemp.GetStateString());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s, better lastPing: %d min ago, projected mn state: %s\n", hash.ToString(), pfrom->addr.ToString(), (GetTime() - mnb.lastPing.sigTime)/60, mnTemp.GetStateString());
|
||||||
if(mnTemp.IsValidStateForAutoStart(mnTemp.nActiveState)) {
|
if(mnTemp.IsValidStateForAutoStart(mnTemp.nActiveState)) {
|
||||||
// this node thinks it's a good one
|
// this node thinks it's a good one
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen good\n", mnb.vin.prevout.ToStringShort());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen good\n", mnb.vin.prevout.ToStringShort());
|
||||||
mMnbRecoveryGoodReplies[hash].push_back(mnb);
|
mMnbRecoveryGoodReplies[hash].push_back(mnb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
mapSeenMasternodeBroadcast.insert(std::make_pair(hash, std::make_pair(GetTime(), mnb)));
|
||||||
}
|
|
||||||
mapSeenMasternodeBroadcast.insert(std::make_pair(hash, std::make_pair(GetTime(), mnb)));
|
|
||||||
|
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.vin.prevout.ToStringShort());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.vin.prevout.ToStringShort());
|
||||||
|
|
||||||
if(!mnb.SimpleCheck(nDos)) {
|
if(!mnb.SimpleCheck(nDos)) {
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- SimpleCheck() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- SimpleCheck() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search Masternode list
|
|
||||||
CMasternode* pmn = Find(mnb.vin);
|
|
||||||
if(pmn) {
|
|
||||||
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
|
|
||||||
if(!mnb.Update(pmn, nDos)) {
|
|
||||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(hash != mnbOld.GetHash()) {
|
|
||||||
mapSeenMasternodeBroadcast.erase(mnbOld.GetHash());
|
// search Masternode list
|
||||||
}
|
CMasternode* pmn = Find(mnb.vin);
|
||||||
} else {
|
if(pmn) {
|
||||||
if(mnb.CheckOutpoint(nDos)) {
|
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast[CMasternodeBroadcast(*pmn).GetHash()].second;
|
||||||
Add(mnb);
|
if(!mnb.Update(pmn, nDos)) {
|
||||||
masternodeSync.AddedMasternodeList();
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
||||||
// if it matches our Masternode privkey...
|
return false;
|
||||||
if(fMasterNode && mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode) {
|
|
||||||
mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
|
|
||||||
if(mnb.nProtocolVersion == PROTOCOL_VERSION) {
|
|
||||||
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
|
|
||||||
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Got NEW Masternode entry: masternode=%s sigTime=%lld addr=%s\n",
|
|
||||||
mnb.vin.prevout.ToStringShort(), mnb.sigTime, mnb.addr.ToString());
|
|
||||||
activeMasternode.ManageState();
|
|
||||||
} else {
|
|
||||||
// ... otherwise we need to reactivate our node, do not add it to the list and do not relay
|
|
||||||
// but also do not ban the node we get this message from
|
|
||||||
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", mnb.nProtocolVersion, PROTOCOL_VERSION);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mnb.Relay();
|
if(hash != mnbOld.GetHash()) {
|
||||||
} else {
|
mapSeenMasternodeBroadcast.erase(mnbOld.GetHash());
|
||||||
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Rejected Masternode entry: %s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mnb.CheckOutpoint(nDos)) {
|
||||||
|
Add(mnb);
|
||||||
|
masternodeSync.AddedMasternodeList();
|
||||||
|
// if it matches our Masternode privkey...
|
||||||
|
if(fMasterNode && mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode) {
|
||||||
|
mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
|
||||||
|
if(mnb.nProtocolVersion == PROTOCOL_VERSION) {
|
||||||
|
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
|
||||||
|
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Got NEW Masternode entry: masternode=%s sigTime=%lld addr=%s\n",
|
||||||
|
mnb.vin.prevout.ToStringShort(), mnb.sigTime, mnb.addr.ToString());
|
||||||
|
activeMasternode.ManageState();
|
||||||
|
} else {
|
||||||
|
// ... otherwise we need to reactivate our node, do not add it to the list and do not relay
|
||||||
|
// but also do not ban the node we get this message from
|
||||||
|
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", mnb.nProtocolVersion, PROTOCOL_VERSION);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mnb.Relay();
|
||||||
|
} else {
|
||||||
|
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Rejected Masternode entry: %s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user