From 40f3d98f97766115909c9d87efffd13638f2ebfc Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 2 Jul 2025 13:33:12 +0700 Subject: [PATCH 1/7] refactor: simplify GetLastMinedCommitmentsPerQuorumIndexUntilBlock interface --- src/llmq/blockprocessor.cpp | 21 ++++++++++----------- src/llmq/blockprocessor.h | 4 +++- src/llmq/snapshot.cpp | 7 ++++--- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index e554948a7429..cd0f1b19370d 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -572,16 +572,17 @@ std::optional CQuorumBlockProcessor::GetLastMinedCommitments return std::nullopt; } -std::vector> CQuorumBlockProcessor::GetLastMinedCommitmentsPerQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t cycle) const +std::vector CQuorumBlockProcessor::GetLastMinedCommitmentsPerQuorumIndexUntilBlock( + Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t cycle) const { const auto& llmq_params_opt = Params().GetLLMQ(llmqType); assert(llmq_params_opt.has_value()); - std::vector> ret; + std::vector ret; for (const auto quorumIndex : irange::range(llmq_params_opt->signingActiveQuorumCount)) { std::optional q = GetLastMinedCommitmentsByQuorumIndexUntilBlock(llmqType, pindex, quorumIndex, cycle); if (q.has_value()) { - ret.emplace_back(quorumIndex, q.value()); + ret.emplace_back(q.value()); } } @@ -595,17 +596,15 @@ std::vector CQuorumBlockProcessor::GetMinedCommitmentsIndexe size_t cycle = 0; while (ret.size() < maxCount) { - std::vector> cycleRet = GetLastMinedCommitmentsPerQuorumIndexUntilBlock(llmqType, pindex, cycle); + std::vector cycleRet = GetLastMinedCommitmentsPerQuorumIndexUntilBlock(llmqType, pindex, cycle); if (cycleRet.empty()) { return ret; } std::vector cycleRetTransformed; - std::transform(cycleRet.begin(), - cycleRet.end(), - std::back_inserter(cycleRetTransformed), - [](const std::pair& p) { return p.second; }); + std::transform(cycleRet.begin(), cycleRet.end(), std::back_inserter(cycleRetTransformed), + [](const CBlockIndex* pindex) { return pindex; }); size_t needToCopy = maxCount - ret.size(); @@ -627,9 +626,9 @@ std::map> CQuorumBlockProce auto& v = ret[params.type]; v.reserve(params.signingActiveQuorumCount); if (IsQuorumRotationEnabled(params, pindex)) { - std::vector> commitments = GetLastMinedCommitmentsPerQuorumIndexUntilBlock(params.type, pindex, 0); - std::transform(commitments.begin(), commitments.end(), std::back_inserter(v), - [](const std::pair& p) { return p.second; }); + std::vector commitments = GetLastMinedCommitmentsPerQuorumIndexUntilBlock(params.type, + pindex, 0); + std::copy(commitments.begin(), commitments.end(), std::back_inserter(v)); } else { auto commitments = GetMinedCommitmentsUntilBlock(params.type, pindex, params.signingActiveQuorumCount); std::copy(commitments.begin(), commitments.end(), std::back_inserter(v)); diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index 170e0007f742..705fe8e332b5 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -71,7 +71,9 @@ class CQuorumBlockProcessor std::map> GetMinedAndActiveCommitmentsUntilBlock(gsl::not_null pindex) const; std::vector GetMinedCommitmentsIndexedUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t maxCount) const; - std::vector> GetLastMinedCommitmentsPerQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t cycle) const; + std::vector GetLastMinedCommitmentsPerQuorumIndexUntilBlock(Consensus::LLMQType llmqType, + const CBlockIndex* pindex, + size_t cycle) const; std::optional GetLastMinedCommitmentsByQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, int quorumIndex, size_t cycle) const; private: static bool GetCommitmentsFromBlock(const CBlock& block, gsl::not_null pindex, std::multimap& ret, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index b0097798e409..03f2baba1c0e 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -294,17 +294,18 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, CQuorumSnapshotMan std::set snapshotHeightsNeeded; - std::vector> qdata = qblockman.GetLastMinedCommitmentsPerQuorumIndexUntilBlock(llmqType, blockIndex, 0); + std::vector qdata = qblockman.GetLastMinedCommitmentsPerQuorumIndexUntilBlock(llmqType, + blockIndex, 0); for (const auto& obj : qdata) { uint256 minedBlockHash; - llmq::CFinalCommitmentPtr qc = qblockman.GetMinedCommitment(llmqType, obj.second->GetBlockHash(), minedBlockHash); + llmq::CFinalCommitmentPtr qc = qblockman.GetMinedCommitment(llmqType, obj->GetBlockHash(), minedBlockHash); if (qc == nullptr) { return false; } response.lastCommitmentPerIndex.push_back(*qc); - int quorumCycleStartHeight = obj.second->nHeight - (obj.second->nHeight % llmq_params_opt->dkgInterval); + int quorumCycleStartHeight = obj->nHeight - (obj->nHeight % llmq_params_opt->dkgInterval); snapshotHeightsNeeded.insert(quorumCycleStartHeight - cycleLength); snapshotHeightsNeeded.insert(quorumCycleStartHeight - 2 * cycleLength); snapshotHeightsNeeded.insert(quorumCycleStartHeight - 3 * cycleLength); From 6d9018946d0542a984946ac72dd674117a07a62b Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 2 Jul 2025 13:35:36 +0700 Subject: [PATCH 2/7] refactor: futher simplification of GetMinedAndActiveCommitmentsUntilBlock and related code --- src/llmq/blockprocessor.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index cd0f1b19370d..b3ae63677d08 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -602,15 +602,8 @@ std::vector CQuorumBlockProcessor::GetMinedCommitmentsIndexe return ret; } - std::vector cycleRetTransformed; - std::transform(cycleRet.begin(), cycleRet.end(), std::back_inserter(cycleRetTransformed), - [](const CBlockIndex* pindex) { return pindex; }); - size_t needToCopy = maxCount - ret.size(); - - std::copy_n(cycleRetTransformed.begin(), - std::min(needToCopy, cycleRetTransformed.size()), - std::back_inserter(ret)); + std::copy_n(cycleRet.begin(), std::min(needToCopy, cycleRet.size()), std::back_inserter(ret)); cycle++; } @@ -623,15 +616,11 @@ std::map> CQuorumBlockProce std::map> ret; for (const auto& params : Params().GetConsensus().llmqs) { - auto& v = ret[params.type]; - v.reserve(params.signingActiveQuorumCount); + auto& commitments = ret[params.type]; if (IsQuorumRotationEnabled(params, pindex)) { - std::vector commitments = GetLastMinedCommitmentsPerQuorumIndexUntilBlock(params.type, - pindex, 0); - std::copy(commitments.begin(), commitments.end(), std::back_inserter(v)); + commitments = GetLastMinedCommitmentsPerQuorumIndexUntilBlock(params.type, pindex, 0); } else { - auto commitments = GetMinedCommitmentsUntilBlock(params.type, pindex, params.signingActiveQuorumCount); - std::copy(commitments.begin(), commitments.end(), std::back_inserter(v)); + commitments = GetMinedCommitmentsUntilBlock(params.type, pindex, params.signingActiveQuorumCount); } } From d78fb0203f42d0b29be7ada0b11bc49b951ea852 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 15 Jul 2025 02:20:46 +0700 Subject: [PATCH 3/7] perf: replace re-creation of CFinalCommitment and extra unique_ptr to RVO CFinalCommitment is a heavy object to create and copy --- src/evo/cbtx.cpp | 9 ++++----- src/llmq/blockprocessor.cpp | 11 +++++++++++ src/llmq/blockprocessor.h | 1 + 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 0ea054809917..0cf579c97eee 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -96,15 +96,14 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: vec_hashes.reserve(vecBlockIndexes.size()); auto& map_indexed_hashes = qcIndexedHashes_cached[llmqType]; for (const auto& blockIndex : vecBlockIndexes) { - uint256 dummyHash; - llmq::CFinalCommitmentPtr pqc = quorum_block_processor.GetMinedCommitment(llmqType, blockIndex->GetBlockHash(), dummyHash); - if (pqc == nullptr) { + const auto [pqc, dummyHash] = quorum_block_processor.GetMinedCommitment(llmqType, blockIndex->GetBlockHash()); + if (dummyHash == uint256::ZERO) { // this should never happen return std::nullopt; } - auto qcHash = ::SerializeHash(*pqc); + auto qcHash = ::SerializeHash(pqc); if (rotation_enabled) { - map_indexed_hashes[pqc->quorumIndex] = qcHash; + map_indexed_hashes[pqc.quorumIndex] = qcHash; } else { vec_hashes.emplace_back(qcHash); } diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index b3ae63677d08..12ab73f3ad82 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -479,6 +479,17 @@ CFinalCommitmentPtr CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQTyp return std::make_unique(p.first); } +std::pair CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, + const uint256& quorumHash) const +{ + auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair(llmqType, quorumHash)); + std::pair ret; + if (!m_evoDb.Read(key, ret)) { + return {CFinalCommitment{}, uint256::ZERO}; + } + return ret; +} + // The returned quorums are in reversed order, so the most recent one is at index 0 std::vector CQuorumBlockProcessor::GetMinedCommitmentsUntilBlock(Consensus::LLMQType llmqType, gsl::not_null pindex, size_t maxCount) const { diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index 705fe8e332b5..068c8cd1ad5c 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -66,6 +66,7 @@ class CQuorumBlockProcessor bool GetMineableCommitmentsTx(const Consensus::LLMQParams& llmqParams, int nHeight, std::vector& ret) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); bool HasMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash) const; CFinalCommitmentPtr GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, uint256& retMinedBlockHash) const; + std::pair GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash) const; std::vector GetMinedCommitmentsUntilBlock(Consensus::LLMQType llmqType, gsl::not_null pindex, size_t maxCount) const; std::map> GetMinedAndActiveCommitmentsUntilBlock(gsl::not_null pindex) const; From f2b2479ec938b2cbd18c9945bf2102dd2ac3d3da Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 15 Jul 2025 02:33:22 +0700 Subject: [PATCH 4/7] refactor: avoid code duplication due to 2 implementation of GetMinedCommitment --- src/evo/smldiff.cpp | 7 +++---- src/llmq/blockprocessor.cpp | 11 ----------- src/llmq/blockprocessor.h | 3 --- src/llmq/quorums.cpp | 12 ++++++------ src/llmq/snapshot.cpp | 7 +++---- 5 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/evo/smldiff.cpp b/src/evo/smldiff.cpp index e0e9bf6d5a17..5ba1e06358f3 100644 --- a/src/evo/smldiff.cpp +++ b/src/evo/smldiff.cpp @@ -54,12 +54,11 @@ bool CSimplifiedMNListDiff::BuildQuorumsDiff(const CBlockIndex* baseBlockIndex, for (const auto& p : quorumHashes) { const auto& [llmqType, hash] = p; if (!baseQuorumHashes.count(p)) { - uint256 minedBlockHash; - llmq::CFinalCommitmentPtr qc = quorum_block_processor.GetMinedCommitment(llmqType, hash, minedBlockHash); - if (qc == nullptr) { + auto [qc, minedBlockHash] = quorum_block_processor.GetMinedCommitment(llmqType, hash); + if (minedBlockHash == uint256::ZERO) { return false; } - newQuorums.emplace_back(*qc); + newQuorums.emplace_back(std::move(qc)); } } diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index 12ab73f3ad82..739601afb980 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -468,17 +468,6 @@ bool CQuorumBlockProcessor::HasMinedCommitment(Consensus::LLMQType llmqType, con return fExists; } -CFinalCommitmentPtr CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, uint256& retMinedBlockHash) const -{ - auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair(llmqType, quorumHash)); - std::pair p; - if (!m_evoDb.Read(key, p)) { - return nullptr; - } - retMinedBlockHash = p.second; - return std::make_unique(p.first); -} - std::pair CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash) const { diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index 068c8cd1ad5c..f8f195fcd73b 100644 --- a/src/llmq/blockprocessor.h +++ b/src/llmq/blockprocessor.h @@ -33,8 +33,6 @@ namespace llmq class CFinalCommitment; class CQuorumSnapshotManager; -using CFinalCommitmentPtr = std::unique_ptr; - class CQuorumBlockProcessor { private: @@ -65,7 +63,6 @@ class CQuorumBlockProcessor std::optional> GetMineableCommitments(const Consensus::LLMQParams& llmqParams, int nHeight) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); bool GetMineableCommitmentsTx(const Consensus::LLMQParams& llmqParams, int nHeight, std::vector& ret) const EXCLUSIVE_LOCKS_REQUIRED(::cs_main); bool HasMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash) const; - CFinalCommitmentPtr GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, uint256& retMinedBlockHash) const; std::pair GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash) const; std::vector GetMinedCommitmentsUntilBlock(Consensus::LLMQType llmqType, gsl::not_null pindex, size_t maxCount) const; diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index de1b3815c59b..d7eeef7ecd1b 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -399,20 +399,20 @@ void CQuorumManager::CheckQuorumConnections(CConnman& connman, const Consensus:: CQuorumPtr CQuorumManager::BuildQuorumFromCommitment(const Consensus::LLMQType llmqType, gsl::not_null pQuorumBaseBlockIndex, bool populate_cache) const { const uint256& quorumHash{pQuorumBaseBlockIndex->GetBlockHash()}; - uint256 minedBlockHash; - CFinalCommitmentPtr qc = quorumBlockProcessor.GetMinedCommitment(llmqType, quorumHash, minedBlockHash); - if (qc == nullptr) { + + auto [qc, minedBlockHash] = quorumBlockProcessor.GetMinedCommitment(llmqType, quorumHash); + if (minedBlockHash == uint256::ZERO) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- No mined commitment for llmqType[%d] nHeight[%d] quorumHash[%s]\n", __func__, ToUnderlying(llmqType), pQuorumBaseBlockIndex->nHeight, pQuorumBaseBlockIndex->GetBlockHash().ToString()); return nullptr; } - assert(qc->quorumHash == pQuorumBaseBlockIndex->GetBlockHash()); + assert(qc.quorumHash == pQuorumBaseBlockIndex->GetBlockHash()); const auto& llmq_params_opt = Params().GetLLMQ(llmqType); assert(llmq_params_opt.has_value()); auto quorum = std::make_shared(llmq_params_opt.value(), blsWorker); - auto members = utils::GetAllQuorumMembers(qc->llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); + auto members = utils::GetAllQuorumMembers(qc.llmqType, m_dmnman, m_qsnapman, pQuorumBaseBlockIndex); - quorum->Init(std::move(qc), pQuorumBaseBlockIndex, minedBlockHash, members); + quorum->Init(std::make_unique(std::move(qc)), pQuorumBaseBlockIndex, minedBlockHash, members); if (populate_cache && llmq_params_opt->size == 1) { WITH_LOCK(cs_map_quorums, mapQuorumsCache[llmqType].insert(quorumHash, quorum)); diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index 03f2baba1c0e..a0e6cf35958a 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -298,12 +298,11 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, CQuorumSnapshotMan blockIndex, 0); for (const auto& obj : qdata) { - uint256 minedBlockHash; - llmq::CFinalCommitmentPtr qc = qblockman.GetMinedCommitment(llmqType, obj->GetBlockHash(), minedBlockHash); - if (qc == nullptr) { + auto [qc, minedBlockHash] = qblockman.GetMinedCommitment(llmqType, obj->GetBlockHash()); + if (minedBlockHash == uint256::ZERO) { return false; } - response.lastCommitmentPerIndex.push_back(*qc); + response.lastCommitmentPerIndex.emplace_back(std::move(qc)); int quorumCycleStartHeight = obj->nHeight - (obj->nHeight % llmq_params_opt->dkgInterval); snapshotHeightsNeeded.insert(quorumCycleStartHeight - cycleLength); From 89581527f28904d9c2bfbf1aa1a276cbf69bdd65 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Fri, 4 Jul 2025 23:18:37 +0700 Subject: [PATCH 5/7] perf: cache mined commitment for quorum merkle root calculation --- src/evo/cbtx.cpp | 28 ++++++++++++++++++++-------- src/llmq/utils.cpp | 4 ++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 0cf579c97eee..6af96c26dc72 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -74,11 +75,12 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: static Mutex cs_cache; static std::map> quorums_cached GUARDED_BY(cs_cache); + static std::map, StaticSaltedHasher>> qc_hashes_cached + GUARDED_BY(cs_cache); static QcHashMap qcHashes_cached GUARDED_BY(cs_cache); static QcIndexedHashMap qcIndexedHashes_cached GUARDED_BY(cs_cache); LOCK(cs_cache); - if (quorums == quorums_cached) { return std::make_pair(qcHashes_cached, qcIndexedHashes_cached); } @@ -87,6 +89,9 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: quorums_cached.clear(); qcHashes_cached.clear(); qcIndexedHashes_cached.clear(); + if (qc_hashes_cached.empty()) { + llmq::utils::InitQuorumsCache(qc_hashes_cached); + } for (const auto& [llmqType, vecBlockIndexes] : quorums) { const auto& llmq_params_opt = Params().GetLLMQ(llmqType); @@ -96,16 +101,23 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: vec_hashes.reserve(vecBlockIndexes.size()); auto& map_indexed_hashes = qcIndexedHashes_cached[llmqType]; for (const auto& blockIndex : vecBlockIndexes) { - const auto [pqc, dummyHash] = quorum_block_processor.GetMinedCommitment(llmqType, blockIndex->GetBlockHash()); - if (dummyHash == uint256::ZERO) { - // this should never happen - return std::nullopt; + uint256 block_hash{blockIndex->GetBlockHash()}; + + std::pair qc_hash; + if (!qc_hashes_cached[llmqType].get(block_hash, qc_hash)) { + auto [pqc, dummy_hash] = quorum_block_processor.GetMinedCommitment(llmqType, block_hash); + if (dummy_hash == uint256::ZERO) { + // this should never happen + return std::nullopt; + } + qc_hash.first = ::SerializeHash(pqc); + qc_hash.second = rotation_enabled ? pqc.quorumIndex : 0; + qc_hashes_cached[llmqType].insert(block_hash, qc_hash); } - auto qcHash = ::SerializeHash(pqc); if (rotation_enabled) { - map_indexed_hashes[pqc.quorumIndex] = qcHash; + map_indexed_hashes[qc_hash.second] = qc_hash.first; } else { - vec_hashes.emplace_back(qcHash); + vec_hashes.emplace_back(qc_hash.first); } } } diff --git a/src/llmq/utils.cpp b/src/llmq/utils.cpp index b64b573c88a7..d8ff21d5ca69 100644 --- a/src/llmq/utils.cpp +++ b/src/llmq/utils.cpp @@ -953,5 +953,9 @@ template void InitQuorumsCache, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>>(std::map, StaticSaltedHasher, 0ul, 0ul>, std::less, std::allocator, StaticSaltedHasher, 0ul, 0ul>>>>&cache, bool limit_by_connections); template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); template void InitQuorumsCache>>(std::map>& cache, bool limit_by_connections); +template void +InitQuorumsCache, StaticSaltedHasher>>>( + std::map, StaticSaltedHasher>>& cache, + bool limit_by_connections); } // namespace utils } // namespace llmq From 8254e064856b11940eee88c1b271df5beba98b7a Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 22 Jul 2025 22:09:07 +0700 Subject: [PATCH 6/7] refactor: resolve freshly introduced circular dependency --- src/evo/smldiff.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/evo/smldiff.cpp b/src/evo/smldiff.cpp index 5ba1e06358f3..0de5434fb194 100644 --- a/src/evo/smldiff.cpp +++ b/src/evo/smldiff.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -23,6 +22,9 @@ using node::ReadBlockFromDisk; +// Forward declaration +std::optional> GetNonNullCoinbaseChainlock(const CBlockIndex* pindex); + CSimplifiedMNListDiff::CSimplifiedMNListDiff() = default; CSimplifiedMNListDiff::~CSimplifiedMNListDiff() = default; From eeb577b3e7c8334585620513059fa7707edbce48 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Fri, 4 Jul 2025 23:28:16 +0700 Subject: [PATCH 7/7] perf: swap arrays instead assigments to save allocation --- src/evo/cbtx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 6af96c26dc72..714548f0f813 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -121,7 +121,7 @@ auto CachedGetQcHashesQcIndexedHashes(const CBlockIndex* pindexPrev, const llmq: } } } - quorums_cached = quorums; + std::swap(quorums_cached, quorums); return std::make_pair(qcHashes_cached, qcIndexedHashes_cached); }