From 8e4fe3660e3b5da993194416955f221341775d1b Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 15 Jan 2019 16:05:26 +0300 Subject: [PATCH] [PrivateSend] Fallback to less participants if possible, fix too long timeouts on server side (#2616) * Fallback to less participants on timeouts if possible * Only bump nTimeLastSuccessfulStep when state is changed * Consistency: always set state first before relaying smth to clients --- src/privatesend-server.cpp | 39 ++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/privatesend-server.cpp b/src/privatesend-server.cpp index ed74f83bccd59..c299ce00ebc6a 100644 --- a/src/privatesend-server.cpp +++ b/src/privatesend-server.cpp @@ -244,7 +244,6 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm RelayStatus(STATUS_ACCEPTED, connman); } else { PushStatus(pfrom, STATUS_REJECTED, nMessageID, connman); - SetNull(); } } else if (strCommand == NetMsgType::DSSIGNFINALTX) { @@ -332,8 +331,8 @@ void CPrivateSendServer::CreateFinalTransaction(CConnman& connman) LogPrint("privatesend", "CPrivateSendServer::CreateFinalTransaction -- finalMutableTransaction=%s", txNew.ToString()); // request signatures from clients - RelayFinalTransaction(finalMutableTransaction, connman); SetState(POOL_STATE_SIGNING); + RelayFinalTransaction(finalMutableTransaction, connman); } void CPrivateSendServer::CommitFinalTransaction(CConnman& connman) @@ -484,7 +483,7 @@ void CPrivateSendServer::ChargeRandomFees(CConnman& connman) CValidationState state; if (!AcceptToMemoryPool(mempool, state, txCollateral, false, NULL, false, maxTxFee)) { - // should never really happen + // Can happen if this collateral belongs to some misbehaving participant we punished earlier LogPrintf("CPrivateSendServer::ChargeRandomFees -- ERROR: AcceptToMemoryPool failed!\n"); } else { connman.RelayTransaction(*txCollateral); @@ -498,18 +497,40 @@ void CPrivateSendServer::ChargeRandomFees(CConnman& connman) void CPrivateSendServer::CheckTimeout(CConnman& connman) { if (!fMasternodeMode) return; + if (nState == POOL_STATE_IDLE) return; CheckQueue(); int nTimeout = (nState == POOL_STATE_SIGNING) ? PRIVATESEND_SIGNING_TIMEOUT : PRIVATESEND_QUEUE_TIMEOUT; bool fTimeout = GetTime() - nTimeLastSuccessfulStep >= nTimeout; - if (nState != POOL_STATE_IDLE && fTimeout) { - LogPrint("privatesend", "CPrivateSendServer::CheckTimeout -- %s timed out (%ds) -- resetting\n", - (nState == POOL_STATE_SIGNING) ? "Signing" : "Session", nTimeout); + // Too early to do anything + if (!fTimeout) return; + + // See if we have at least min number of participants, if so - we can still do smth + if (nState == POOL_STATE_QUEUE && vecSessionCollaterals.size() >= CPrivateSend::GetMinPoolParticipants()) { + LogPrint("privatesend", "CPrivateSendServer::CheckTimeout -- Queue for %d participants timed out (%ds) -- falling back to %d participants\n", + nSessionMaxParticipants, nTimeout, vecSessionCollaterals.size()); + nSessionMaxParticipants = vecSessionCollaterals.size(); + return; + } + + if (nState == POOL_STATE_ACCEPTING_ENTRIES && GetEntriesCount() >= CPrivateSend::GetMinPoolParticipants()) { + LogPrint("privatesend", "CPrivateSendServer::CheckTimeout -- Accepting entries for %d participants timed out (%ds) -- falling back to %d participants\n", + nSessionMaxParticipants, nTimeout, GetEntriesCount()); + // Punish misbehaving participants ChargeFees(connman); - SetNull(); + // Try to complete this session ignoring the misbehaving ones + nSessionMaxParticipants = GetEntriesCount(); + CheckPool(connman); + return; } + + // All other cases + LogPrint("privatesend", "CPrivateSendServer::CheckTimeout -- %s timed out (%ds) -- resetting\n", + (nState == POOL_STATE_SIGNING) ? "Signing" : "Session", nTimeout); + ChargeFees(connman); + SetNull(); } /* @@ -617,7 +638,6 @@ bool CPrivateSendServer::AddEntry(const CPrivateSendEntry& entryNew, PoolMessage LogPrint("privatesend", "CPrivateSendServer::AddEntry -- adding entry %d of %d required\n", GetEntriesCount(), nSessionMaxParticipants); nMessageIDRet = MSG_ENTRIES_ADDED; - nTimeLastSuccessfulStep = GetTime(); return true; } @@ -726,7 +746,6 @@ bool CPrivateSendServer::CreateNewSession(const CPrivateSendAccept& dsa, PoolMes nSessionMaxParticipants = CPrivateSend::GetMinPoolParticipants() + GetRandInt(CPrivateSend::GetMaxPoolParticipants() - CPrivateSend::GetMinPoolParticipants() + 1); SetState(POOL_STATE_QUEUE); - nTimeLastSuccessfulStep = GetTime(); if (!fUnitTest) { //broadcast that I'm accepting entries, only if it's the first entry through @@ -769,7 +788,6 @@ bool CPrivateSendServer::AddUserToExistingSession(const CPrivateSendAccept& dsa, // count new user as accepted to an existing session nMessageIDRet = MSG_NOERR; - nTimeLastSuccessfulStep = GetTime(); vecSessionCollaterals.push_back(MakeTransactionRef(dsa.txCollateral)); LogPrintf("CPrivateSendServer::AddUserToExistingSession -- new user accepted, nSessionID: %d nSessionDenom: %d (%s) vecSessionCollaterals.size(): %d nSessionMaxParticipants: %d\n", @@ -876,6 +894,7 @@ void CPrivateSendServer::SetState(PoolState nStateNew) } LogPrintf("CPrivateSendServer::SetState -- nState: %d, nStateNew: %d\n", nState, nStateNew); + nTimeLastSuccessfulStep = GetTime(); nState = nStateNew; }