@@ -331,13 +331,33 @@ 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+ {
342+ LOCK (cached_mutex);
343+ cached_chainlock = std::make_pair (cbTx.bestCLSignature , cbTx.bestCLHeightDiff );
344+ cached_pindex = pindex;
345+ }
337346 return true ;
338347 }
339348
340- const auto prevBlockCoinbaseChainlock = GetNonNullCoinbaseChainlock (pindex->pprev );
349+ std::optional<std::pair<CBLSSignature, uint32_t >> prevBlockCoinbaseChainlock{std::nullopt };
350+ bool use_cached = false ;
351+ {
352+ LOCK (cached_mutex);
353+ if (cached_pindex == pindex->pprev ) {
354+ use_cached = true ;
355+ prevBlockCoinbaseChainlock = cached_chainlock;
356+ }
357+ }
358+ if (!use_cached) {
359+ prevBlockCoinbaseChainlock = GetNonNullCoinbaseChainlock (pindex->pprev );
360+ }
341361 // If std::optional prevBlockCoinbaseChainlock is empty, then up to the previous block, coinbase Chainlock is null.
342362 if (prevBlockCoinbaseChainlock.has_value ()) {
343363 // 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 +375,22 @@ bool CheckCbTxBestChainlock(const CBlock& block, const CBlockIndex* pindex,
355375 int curBlockCoinbaseCLHeight = pindex->nHeight - static_cast <int >(cbTx.bestCLHeightDiff ) - 1 ;
356376 if (best_clsig.getHeight () == curBlockCoinbaseCLHeight && best_clsig.getSig () == cbTx.bestCLSignature ) {
357377 // matches our best (but outdated) clsig, no need to verify it again
378+ {
379+ LOCK (cached_mutex);
380+ cached_chainlock = std::make_pair (cbTx.bestCLSignature , cbTx.bestCLHeightDiff );
381+ cached_pindex = pindex;
382+ }
358383 return true ;
359384 }
360385 uint256 curBlockCoinbaseCLBlockHash = pindex->GetAncestor (curBlockCoinbaseCLHeight)->GetBlockHash ();
361386 if (chainlock_handler.VerifyChainLock (llmq::CChainLockSig (curBlockCoinbaseCLHeight, curBlockCoinbaseCLBlockHash, cbTx.bestCLSignature )) != llmq::VerifyRecSigStatus::Valid) {
362387 return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-cbtx-invalid-clsig" );
363388 }
389+ {
390+ LOCK (cached_mutex);
391+ cached_chainlock = std::make_pair (cbTx.bestCLSignature , cbTx.bestCLHeightDiff );
392+ cached_pindex = pindex;
393+ }
364394 } else if (cbTx.bestCLHeightDiff != 0 ) {
365395 // Null bestCLSignature is allowed only with bestCLHeightDiff = 0
366396 return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-cbtx-cldiff" );
@@ -437,6 +467,10 @@ std::optional<std::pair<CBLSSignature, uint32_t>> GetNonNullCoinbaseChainlock(co
437467 return std::nullopt ;
438468 }
439469
470+ // There's no CL in CbTx before v20 activation
471+ if (!DeploymentActiveAt (*pindex, Params ().GetConsensus (), Consensus::DEPLOYMENT_V20)) {
472+ return std::nullopt ;
473+ }
440474 // There's no CbTx before DIP0003 activation
441475 if (!DeploymentActiveAt (*pindex, Params ().GetConsensus (), Consensus::DEPLOYMENT_DIP0003)) {
442476 return std::nullopt ;
0 commit comments