Skip to content

Commit 9dda5d2

Browse files
codablockpanleone
authored andcommitted
Implement LLMQ based InstantSend (#2735)
* Move ChainLock signing into TrySignChainTip and call it periodically * Cheaper/Faster bailout from TrySignChainTip when already signed before
1 parent 149e3e3 commit 9dda5d2

File tree

2 files changed

+54
-16
lines changed

2 files changed

+54
-16
lines changed

src/llmq/quorums_chainlocks.cpp

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ CChainLocksHandler::~CChainLocksHandler()
3939
void CChainLocksHandler::Start()
4040
{
4141
quorumSigningManager->RegisterRecoveredSigsListener(this);
42+
scheduler->scheduleEvery([&]() {
43+
// regularely retry signing the current chaintip
44+
TrySignChainTip();
45+
},
46+
5000);
4247
}
4348

4449
void CChainLocksHandler::Stop()
@@ -180,55 +185,86 @@ void CChainLocksHandler::AcceptedBlockHeader(const CBlockIndex* pindexNew)
180185

181186
void CChainLocksHandler::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork)
182187
{
188+
// don't call TrySignChainTip directly but instead let the scheduler call it. This way we ensure that cs_main is
189+
// never locked and TrySignChainTip is not called twice in parallel
190+
LOCK(cs);
191+
if (tryLockChainTipScheduled) {
192+
return;
193+
}
194+
tryLockChainTipScheduled = true;
195+
scheduler->scheduleFromNow([&]() {
196+
TrySignChainTip();
197+
LOCK(cs);
198+
tryLockChainTipScheduled = false;
199+
},
200+
0);
201+
}
202+
203+
void CChainLocksHandler::TrySignChainTip()
204+
{
205+
Cleanup();
206+
207+
const CBlockIndex* pindex;
208+
{
209+
LOCK(cs_main);
210+
pindex = chainActive.Tip();
211+
}
212+
183213
if (!fMasterNode) {
184214
return;
185215
}
186-
if (!pindexNew->pprev) {
216+
if (!pindex->pprev) {
187217
return;
188218
}
189219
if (!sporkManager.IsSporkActive(SPORK_23_CHAINLOCKS_ENFORCEMENT)) {
190220
return;
191221
}
192222

193-
Cleanup();
194-
195223
// DIP8 defines a process called "Signing attempts" which should run before the CLSIG is finalized
196224
// To simplify the initial implementation, we skip this process and directly try to create a CLSIG
197225
// This will fail when multiple blocks compete, but we accept this for the initial implementation.
198226
// Later, we'll add the multiple attempts process.
199227

200-
uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, pindexNew->nHeight));
201-
uint256 msgHash = pindexNew->GetBlockHash();
202-
203228
{
204229
LOCK(cs);
205230

206-
if (bestChainLockBlockIndex == pindexNew) {
231+
if (bestChainLockBlockIndex == pindex) {
207232
// we first got the CLSIG, then the header, and then the block was connected.
208233
// In this case there is no need to continue here.
209234
return;
210235
}
211236

212-
if (InternalHasConflictingChainLock(pindexNew->nHeight, pindexNew->GetBlockHash())) {
237+
if (pindex->nHeight == lastSignedHeight) {
238+
// already signed this one
239+
return;
240+
}
241+
242+
if (bestChainLock.nHeight >= pindex->nHeight) {
243+
// already got the same CLSIG or a better one
244+
return;
245+
}
246+
247+
if (InternalHasConflictingChainLock(pindex->nHeight, pindex->GetBlockHash())) {
213248
if (!inEnforceBestChainLock) {
214249
// we accepted this block when there was no lock yet, but now a conflicting lock appeared. Invalidate it.
215250
LogPrintf("CChainLocksHandler::%s -- conflicting lock after block was accepted, invalidating now\n",
216251
__func__);
217-
ScheduleInvalidateBlock(pindexNew);
252+
ScheduleInvalidateBlock(pindex);
218253
}
219254
return;
220255
}
256+
}
221257

222-
if (bestChainLock.nHeight >= pindexNew->nHeight) {
223-
// already got the same CLSIG or a better one
224-
return;
225-
}
258+
uint256 requestId = ::SerializeHash(std::make_pair(CLSIG_REQUESTID_PREFIX, pindex->nHeight));
259+
uint256 msgHash = pindex->GetBlockHash();
226260

227-
if (pindexNew->nHeight == lastSignedHeight) {
228-
// already signed this one
261+
{
262+
LOCK(cs);
263+
if (bestChainLock.nHeight >= pindex->nHeight) {
264+
// might have happened while we didn't hold cs
229265
return;
230266
}
231-
lastSignedHeight = pindexNew->nHeight;
267+
lastSignedHeight = pindex->nHeight;
232268
lastSignedRequestId = requestId;
233269
lastSignedMsgHash = msgHash;
234270
}

src/llmq/quorums_chainlocks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class CChainLocksHandler : public CRecoveredSigsListener
4545
private:
4646
CScheduler* scheduler;
4747
RecursiveMutex cs;
48+
bool tryLockChainTipScheduled{false};
4849
std::atomic<bool> inEnforceBestChainLock{false};
4950

5051
uint256 bestChainLockHash;
@@ -75,6 +76,7 @@ class CChainLocksHandler : public CRecoveredSigsListener
7576
void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash);
7677
void AcceptedBlockHeader(const CBlockIndex* pindexNew);
7778
void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork);
79+
void TrySignChainTip();
7880
void EnforceBestChainLock();
7981
virtual void HandleNewRecoveredSig(const CRecoveredSig& recoveredSig);
8082

0 commit comments

Comments
 (0)