Skip to content

Commit 0a5e8eb

Browse files
committed
Move ChainLock signing into TrySignChainTip and call it periodically
Later commits will introduce checks for "safe TXs" which might abort the signing on first try, but succeed a few seconds later, so we periodically retry to sign the tip.
1 parent bd7edc8 commit 0a5e8eb

File tree

3 files changed

+45
-17
lines changed

3 files changed

+45
-17
lines changed

src/llmq/quorums_chainlocks.cpp

+39-13
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ CChainLocksHandler::~CChainLocksHandler()
3535
{
3636
}
3737

38-
void CChainLocksHandler::RegisterAsRecoveredSigsListener()
38+
void CChainLocksHandler::Start()
3939
{
4040
quorumSigningManager->RegisterRecoveredSigsListener(this);
41+
scheduler->scheduleEvery([&]() {
42+
// regularely retry signing the current chaintip as it might have failed before due to missing ixlocks
43+
TrySignChainTip();
44+
}, 5000);
4145
}
4246

43-
void CChainLocksHandler::UnregisterAsRecoveredSigsListener()
47+
void CChainLocksHandler::Stop()
4448
{
4549
quorumSigningManager->UnregisterRecoveredSigsListener(this);
4650
}
@@ -184,30 +188,52 @@ void CChainLocksHandler::AcceptedBlockHeader(const CBlockIndex* pindexNew)
184188

185189
void CChainLocksHandler::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork)
186190
{
191+
// don't call TrySignChainTip directly but instead let the scheduler call it. This way we ensure that cs_main is
192+
// never locked and TrySignChainTip is not called twice in parallel
193+
LOCK(cs);
194+
if (tryLockChainTipScheduled) {
195+
return;
196+
}
197+
tryLockChainTipScheduled = true;
198+
scheduler->scheduleFromNow([&]() {
199+
TrySignChainTip();
200+
LOCK(cs);
201+
tryLockChainTipScheduled = false;
202+
}, 0);
203+
}
204+
205+
void CChainLocksHandler::TrySignChainTip()
206+
{
207+
Cleanup();
208+
209+
const CBlockIndex* pindex;
210+
{
211+
LOCK(cs_main);
212+
pindex = chainActive.Tip();
213+
}
214+
187215
if (!fMasternodeMode) {
188216
return;
189217
}
190-
if (!pindexNew->pprev) {
218+
if (!pindex->pprev) {
191219
return;
192220
}
193221
if (!sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED)) {
194222
return;
195223
}
196224

197-
Cleanup();
198-
199225
// DIP8 defines a process called "Signing attempts" which should run before the CLSIG is finalized
200226
// To simplify the initial implementation, we skip this process and directly try to create a CLSIG
201227
// This will fail when multiple blocks compete, but we accept this for the initial implementation.
202228
// Later, we'll add the multiple attempts process.
203229

204-
uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, pindexNew->nHeight));
205-
uint256 msgHash = pindexNew->GetBlockHash();
230+
uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, pindex->nHeight));
231+
uint256 msgHash = pindex->GetBlockHash();
206232

207233
{
208234
LOCK(cs);
209235

210-
if (bestChainLockBlockIndex == pindexNew) {
236+
if (bestChainLockBlockIndex == pindex) {
211237
// we first got the CLSIG, then the header, and then the block was connected.
212238
// In this case there is no need to continue here.
213239
// However, NotifyChainLock might not have been called yet, so call it now if needed
@@ -218,26 +244,26 @@ void CChainLocksHandler::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBl
218244
return;
219245
}
220246

221-
if (InternalHasConflictingChainLock(pindexNew->nHeight, pindexNew->GetBlockHash())) {
247+
if (InternalHasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
222248
if (!inEnforceBestChainLock) {
223249
// we accepted this block when there was no lock yet, but now a conflicting lock appeared. Invalidate it.
224250
LogPrintf("CChainLocksHandler::%s -- conflicting lock after block was accepted, invalidating now\n",
225251
__func__);
226-
ScheduleInvalidateBlock(pindexNew);
252+
ScheduleInvalidateBlock(pindex);
227253
}
228254
return;
229255
}
230256

231-
if (bestChainLock.nHeight >= pindexNew->nHeight) {
257+
if (bestChainLock.nHeight >= pindex->nHeight) {
232258
// already got the same CLSIG or a better one
233259
return;
234260
}
235261

236-
if (pindexNew->nHeight == lastSignedHeight) {
262+
if (pindex->nHeight == lastSignedHeight) {
237263
// already signed this one
238264
return;
239265
}
240-
lastSignedHeight = pindexNew->nHeight;
266+
lastSignedHeight = pindex->nHeight;
241267
lastSignedRequestId = requestId;
242268
lastSignedMsgHash = msgHash;
243269
}

src/llmq/quorums_chainlocks.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class CChainLocksHandler : public CRecoveredSigsListener
4949
private:
5050
CScheduler* scheduler;
5151
CCriticalSection cs;
52+
bool tryLockChainTipScheduled{false};
5253
std::atomic<bool> inEnforceBestChainLock{false};
5354

5455
uint256 bestChainLockHash;
@@ -74,8 +75,8 @@ class CChainLocksHandler : public CRecoveredSigsListener
7475
CChainLocksHandler(CScheduler* _scheduler);
7576
~CChainLocksHandler();
7677

77-
void RegisterAsRecoveredSigsListener();
78-
void UnregisterAsRecoveredSigsListener();
78+
void Start();
79+
void Stop();
7980

8081
bool AlreadyHave(const CInv& inv);
8182
bool GetChainLockByHash(const uint256& hash, CChainLockSig& ret);
@@ -86,6 +87,7 @@ class CChainLocksHandler : public CRecoveredSigsListener
8687
void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork);
8788
void NewPoWValidBlock(const CBlockIndex* pindex, const std::shared_ptr<const CBlock>& block);
8889
void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock);
90+
void TrySignChainTip();
8991
void EnforceBestChainLock();
9092
virtual void HandleNewRecoveredSig(const CRecoveredSig& recoveredSig);
9193

src/llmq/quorums_init.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void StartLLMQSystem()
6666
quorumSigSharesManager->StartWorkerThread();
6767
}
6868
if (chainLocksHandler) {
69-
chainLocksHandler->RegisterAsRecoveredSigsListener();
69+
chainLocksHandler->Start();
7070
}
7171
if (quorumInstantSendManager) {
7272
quorumInstantSendManager->RegisterAsRecoveredSigsListener();
@@ -79,7 +79,7 @@ void StopLLMQSystem()
7979
quorumInstantSendManager->UnregisterAsRecoveredSigsListener();
8080
}
8181
if (chainLocksHandler) {
82-
chainLocksHandler->UnregisterAsRecoveredSigsListener();
82+
chainLocksHandler->Stop();
8383
}
8484
if (quorumSigSharesManager) {
8585
quorumSigSharesManager->StopWorkerThread();

0 commit comments

Comments
 (0)