Skip to content

Commit 18044c9

Browse files
committed
perf: use tiny cache for best chainlock in CbTx instead running heavy ReadBlockFromDisk
1 parent 66c9592 commit 18044c9

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

src/evo/cbtx.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,26 @@ bool CheckCbTxBestChainlock(const CBlock& block, const CBlockIndex* pindex,
331331
return true;
332332
}
333333

334+
static Mutex cached_mutex;
335+
static const CBlockIndex* cached_pindex GUARDED_BY(cached_mutex){nullptr};
336+
static std::optional<std::pair<CBLSSignature, uint32_t>> cached_chainlock GUARDED_BY(cached_mutex){std::nullopt};
337+
334338
auto best_clsig = chainlock_handler.GetBestChainLock();
335339
if (best_clsig.getHeight() == pindex->nHeight - 1 && cbTx.bestCLHeightDiff == 0 && cbTx.bestCLSignature == best_clsig.getSig()) {
336340
// matches our best clsig which still hold values for the previous block
341+
LOCK(cached_mutex);
342+
cached_chainlock = std::make_pair(cbTx.bestCLSignature, cbTx.bestCLHeightDiff);
343+
cached_pindex = pindex;
337344
return true;
338345
}
339346

340-
const auto prevBlockCoinbaseChainlock = GetNonNullCoinbaseChainlock(pindex->pprev);
347+
std::optional<std::pair<CBLSSignature, uint32_t>> prevBlockCoinbaseChainlock{std::nullopt};
348+
if (LOCK(cached_mutex); cached_pindex == pindex->pprev) {
349+
prevBlockCoinbaseChainlock = cached_chainlock;
350+
}
351+
if (!prevBlockCoinbaseChainlock.has_value()) {
352+
prevBlockCoinbaseChainlock = GetNonNullCoinbaseChainlock(pindex->pprev);
353+
}
341354
// If std::optional prevBlockCoinbaseChainlock is empty, then up to the previous block, coinbase Chainlock is null.
342355
if (prevBlockCoinbaseChainlock.has_value()) {
343356
// Previous block Coinbase has a non-null Chainlock: current block's Chainlock must be non-null and at least as new as the previous one
@@ -355,12 +368,18 @@ bool CheckCbTxBestChainlock(const CBlock& block, const CBlockIndex* pindex,
355368
int curBlockCoinbaseCLHeight = pindex->nHeight - static_cast<int>(cbTx.bestCLHeightDiff) - 1;
356369
if (best_clsig.getHeight() == curBlockCoinbaseCLHeight && best_clsig.getSig() == cbTx.bestCLSignature) {
357370
// matches our best (but outdated) clsig, no need to verify it again
371+
LOCK(cached_mutex);
372+
cached_chainlock = std::make_pair(cbTx.bestCLSignature, cbTx.bestCLHeightDiff);
373+
cached_pindex = pindex;
358374
return true;
359375
}
360376
uint256 curBlockCoinbaseCLBlockHash = pindex->GetAncestor(curBlockCoinbaseCLHeight)->GetBlockHash();
361377
if (chainlock_handler.VerifyChainLock(llmq::CChainLockSig(curBlockCoinbaseCLHeight, curBlockCoinbaseCLBlockHash, cbTx.bestCLSignature)) != llmq::VerifyRecSigStatus::Valid) {
362378
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cbtx-invalid-clsig");
363379
}
380+
LOCK(cached_mutex);
381+
cached_chainlock = std::make_pair(cbTx.bestCLSignature, cbTx.bestCLHeightDiff);
382+
cached_pindex = pindex;
364383
} else if (cbTx.bestCLHeightDiff != 0) {
365384
// Null bestCLSignature is allowed only with bestCLHeightDiff = 0
366385
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cbtx-cldiff");

0 commit comments

Comments
 (0)