Skip to content

Commit c42b200

Browse files
committed
Try to avoid being marked as a bad quorum member when we sleep for too long in SleepBeforePhase (#3245)
* Do not sleep at the last block of the phase, it's not safe * Refactor it a bit to make it clearer what's going on here * Stop sleeping if blocks came faster than we expected
1 parent db6ea1d commit c42b200

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

src/llmq/quorums_dkgsessionhandler.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ void CDKGSessionHandler::UpdatedBlockTip(const CBlockIndex* pindexNew)
115115
int quorumStageInt = pindexNew->nHeight % params.dkgInterval;
116116
const CBlockIndex* pindexQuorum = pindexNew->GetAncestor(pindexNew->nHeight - quorumStageInt);
117117

118+
currentHeight = pindexNew->nHeight;
118119
quorumHeight = pindexQuorum->nHeight;
119120
quorumHash = pindexQuorum->GetBlockHash();
120121

@@ -236,22 +237,43 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase,
236237
return;
237238
}
238239

239-
// expected time for a full phase
240-
double phaseTime = params.dkgPhaseBlocks * Params().GetConsensus().nPowTargetSpacing * 1000;
241-
// expected time per member
242-
phaseTime = phaseTime / params.size;
240+
// Two blocks can come very close to each other, this happens pretty regularly. We don't want to be
241+
// left behind and marked as a bad member. This means that we should not count the last block of the
242+
// phase as a safe one to keep sleeping, that's why we calculate the phase sleep time as a time of
243+
// the full phase minus one block here.
244+
double phaseSleepTime = (params.dkgPhaseBlocks - 1) * Params().GetConsensus().nPowTargetSpacing * 1000;
245+
// Expected phase sleep time per member
246+
double phaseSleepTimePerMember = phaseSleepTime / params.size;
243247
// Don't expect perfect block times and thus reduce the phase time to be on the secure side (caller chooses factor)
244-
phaseTime *= randomSleepFactor;
248+
double adjustedPhaseSleepTimePerMember = phaseSleepTimePerMember * randomSleepFactor;
245249

246-
int64_t sleepTime = (int64_t)(phaseTime * curSession->GetMyMemberIndex());
250+
int64_t sleepTime = (int64_t)(adjustedPhaseSleepTimePerMember * curSession->GetMyMemberIndex());
247251
int64_t endTime = GetTimeMillis() + sleepTime;
252+
int heightTmp{-1};
253+
int heightStart{-1};
254+
{
255+
LOCK(cs);
256+
heightTmp = heightStart = currentHeight;
257+
}
248258
while (GetTimeMillis() < endTime) {
249259
if (stopRequested || ShutdownRequested()) {
250260
throw AbortPhaseException();
251261
}
252-
auto p = GetPhaseAndQuorumHash();
253-
if (p.first != curPhase || p.second != expectedQuorumHash) {
254-
throw AbortPhaseException();
262+
{
263+
LOCK(cs);
264+
if (currentHeight > heightTmp) {
265+
// New block(s) just came in
266+
int64_t expectedBlockTime = (currentHeight - heightStart) * Params().GetConsensus().nPowTargetSpacing * 1000;
267+
if (expectedBlockTime > sleepTime) {
268+
// Blocks came faster than we expected, jump into the phase func asap
269+
break;
270+
}
271+
heightTmp = currentHeight;
272+
}
273+
if (phase != curPhase || quorumHash != expectedQuorumHash) {
274+
// Smth went wrong and/or we missed quite a few blocks and it's just too late now
275+
throw AbortPhaseException();
276+
}
255277
}
256278
if (!runWhileWaiting()) {
257279
MilliSleep(100);

src/llmq/quorums_dkgsessionhandler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class CDKGSessionHandler
107107
CDKGSessionManager& dkgManager;
108108

109109
QuorumPhase phase{QuorumPhase_Idle};
110+
int currentHeight{-1};
110111
int quorumHeight{-1};
111112
uint256 quorumHash;
112113
std::shared_ptr<CDKGSession> curSession;

0 commit comments

Comments
 (0)