mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Various fixes for mixing queues (#3138)
* Always check for expired queues on masternodes * Check if a queue is too old or too far into the future Instead of only checking that it's to old * Check that no masternode can spam us with dsqs regardless of dsq readiness
This commit is contained in:
parent
e0c56246f5
commit
152c10bc4b
@ -54,12 +54,17 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
if (q == dsq) {
|
||||
return;
|
||||
}
|
||||
if (q.fReady == dsq.fReady && q.masternodeOutpoint == dsq.masternodeOutpoint) {
|
||||
// no way the same mn can send another dsq with the same readiness this soon
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Peer %s is sending WAY too many dsq messages for a masternode with collateral %s\n", pfrom->GetLogString(), dsq.masternodeOutpoint.ToStringShort());
|
||||
return;
|
||||
}
|
||||
}
|
||||
} // cs_vecqueue
|
||||
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- %s new\n", dsq.ToString());
|
||||
|
||||
if (dsq.IsExpired()) return;
|
||||
if (dsq.IsTimeOutOfBounds()) return;
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
|
||||
@ -83,18 +88,6 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOCK(cs_deqsessions); // have to lock this first to avoid deadlocks with cs_vecqueue
|
||||
TRY_LOCK(cs_vecqueue, lockRecv);
|
||||
if (!lockRecv) return;
|
||||
|
||||
for (const auto& q : vecPrivateSendQueue) {
|
||||
if (q.masternodeOutpoint == dsq.masternodeOutpoint) {
|
||||
// no way same mn can send another "not yet ready" dsq this soon
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->ToString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
|
||||
int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5;
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mmetaman.GetDsqCount());
|
||||
@ -107,12 +100,17 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string&
|
||||
mmetaman.AllowMixing(dmn->proTxHash);
|
||||
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
|
||||
|
||||
LOCK(cs_deqsessions);
|
||||
for (auto& session : deqSessions) {
|
||||
CDeterministicMNCPtr mnMixing;
|
||||
if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->collateralOutpoint == dsq.masternodeOutpoint) {
|
||||
dsq.fTried = true;
|
||||
}
|
||||
}
|
||||
|
||||
TRY_LOCK(cs_vecqueue, lockRecv);
|
||||
if (!lockRecv) return;
|
||||
vecPrivateSendQueue.push_back(dsq);
|
||||
dsq.Relay(connman);
|
||||
}
|
||||
|
@ -97,9 +97,6 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
}
|
||||
|
||||
} else if (strCommand == NetMsgType::DSQUEUE) {
|
||||
TRY_LOCK(cs_vecqueue, lockRecv);
|
||||
if (!lockRecv) return;
|
||||
|
||||
if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) {
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion);
|
||||
connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION)));
|
||||
@ -109,16 +106,26 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
CPrivateSendQueue dsq;
|
||||
vRecv >> dsq;
|
||||
|
||||
// process every dsq only once
|
||||
for (const auto& q : vecPrivateSendQueue) {
|
||||
if (q == dsq) {
|
||||
return;
|
||||
{
|
||||
TRY_LOCK(cs_vecqueue, lockRecv);
|
||||
if (!lockRecv) return;
|
||||
|
||||
// process every dsq only once
|
||||
for (const auto& q : vecPrivateSendQueue) {
|
||||
if (q == dsq) {
|
||||
return;
|
||||
}
|
||||
if (q.fReady == dsq.fReady && q.masternodeOutpoint == dsq.masternodeOutpoint) {
|
||||
// no way the same mn can send another dsq with the same readiness this soon
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Peer %s is sending WAY too many dsq messages for a masternode with collateral %s\n", pfrom->GetLogString(), dsq.masternodeOutpoint.ToStringShort());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // cs_vecqueue
|
||||
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- %s new\n", dsq.ToString());
|
||||
|
||||
if (dsq.IsExpired()) return;
|
||||
if (dsq.IsTimeOutOfBounds()) return;
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint);
|
||||
@ -131,14 +138,6 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
}
|
||||
|
||||
if (!dsq.fReady) {
|
||||
for (const auto& q : vecPrivateSendQueue) {
|
||||
if (q.masternodeOutpoint == dsq.masternodeOutpoint) {
|
||||
// no way same mn can send another "not yet ready" dsq this soon
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->addr.ToString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq();
|
||||
int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5;
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mmetaman.GetDsqCount());
|
||||
@ -150,6 +149,9 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm
|
||||
mmetaman.AllowMixing(dmn->proTxHash);
|
||||
|
||||
LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString());
|
||||
|
||||
TRY_LOCK(cs_vecqueue, lockRecv);
|
||||
if (!lockRecv) return;
|
||||
vecPrivateSendQueue.push_back(dsq);
|
||||
dsq.Relay(connman);
|
||||
}
|
||||
@ -524,10 +526,11 @@ void CPrivateSendServer::ConsumeCollateral(CConnman& connman, const CTransaction
|
||||
void CPrivateSendServer::CheckTimeout(CConnman& connman)
|
||||
{
|
||||
if (!fMasternodeMode) return;
|
||||
if (nState == POOL_STATE_IDLE) return;
|
||||
|
||||
CheckQueue();
|
||||
|
||||
if (nState == POOL_STATE_IDLE) return;
|
||||
|
||||
int nTimeout = (nState == POOL_STATE_SIGNING) ? PRIVATESEND_SIGNING_TIMEOUT : PRIVATESEND_QUEUE_TIMEOUT;
|
||||
bool fTimeout = GetTime() - nTimeLastSuccessfulStep >= nTimeout;
|
||||
|
||||
|
@ -82,6 +82,11 @@ bool CPrivateSendQueue::Relay(CConnman& connman)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPrivateSendQueue::IsTimeOutOfBounds() const
|
||||
{
|
||||
return GetAdjustedTime() - nTime > PRIVATESEND_QUEUE_TIMEOUT || nTime - GetAdjustedTime() > PRIVATESEND_QUEUE_TIMEOUT;
|
||||
}
|
||||
|
||||
uint256 CPrivateSendBroadcastTx::GetSignatureHash() const
|
||||
{
|
||||
return SerializeHash(*this);
|
||||
@ -174,8 +179,8 @@ void CPrivateSendBaseManager::CheckQueue()
|
||||
// check mixing queue objects for timeouts
|
||||
auto it = vecPrivateSendQueue.begin();
|
||||
while (it != vecPrivateSendQueue.end()) {
|
||||
if ((*it).IsExpired()) {
|
||||
LogPrint(BCLog::PRIVATESEND, "CPrivateSendBaseManager::%s -- Removing expired queue (%s)\n", __func__, (*it).ToString());
|
||||
if ((*it).IsTimeOutOfBounds()) {
|
||||
LogPrint(BCLog::PRIVATESEND, "CPrivateSendBaseManager::%s -- Removing a queue (%s)\n", __func__, (*it).ToString());
|
||||
it = vecPrivateSendQueue.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
@ -190,7 +195,7 @@ bool CPrivateSendBaseManager::GetQueueItemAndTry(CPrivateSendQueue& dsqRet)
|
||||
|
||||
for (auto& dsq : vecPrivateSendQueue) {
|
||||
// only try each queue once
|
||||
if (dsq.fTried || dsq.IsExpired()) continue;
|
||||
if (dsq.fTried || dsq.IsTimeOutOfBounds()) continue;
|
||||
dsq.fTried = true;
|
||||
dsqRet = dsq;
|
||||
return true;
|
||||
|
@ -271,8 +271,8 @@ public:
|
||||
|
||||
bool Relay(CConnman& connman);
|
||||
|
||||
/// Is this queue expired?
|
||||
bool IsExpired() { return GetAdjustedTime() - nTime > PRIVATESEND_QUEUE_TIMEOUT; }
|
||||
/// Check if a queue is too old or too far into the future
|
||||
bool IsTimeOutOfBounds() const;
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user