diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 0ea054809917..714548f0f813 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,21 +101,27 @@ 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) { - // 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); } } } - quorums_cached = quorums; + std::swap(quorums_cached, quorums); return std::make_pair(qcHashes_cached, qcIndexedHashes_cached); } diff --git a/src/evo/smldiff.cpp b/src/evo/smldiff.cpp index e0e9bf6d5a17..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; @@ -54,12 +56,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 e554948a7429..739601afb980 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -468,15 +468,15 @@ bool CQuorumBlockProcessor::HasMinedCommitment(Consensus::LLMQType llmqType, con return fExists; } -CFinalCommitmentPtr CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, uint256& retMinedBlockHash) const +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 p; - if (!m_evoDb.Read(key, p)) { - return nullptr; + std::pair ret; + if (!m_evoDb.Read(key, ret)) { + return {CFinalCommitment{}, uint256::ZERO}; } - retMinedBlockHash = p.second; - return std::make_unique(p.first); + return ret; } // The returned quorums are in reversed order, so the most recent one is at index 0 @@ -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,23 +596,14 @@ 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; }); - 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++; } @@ -624,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::transform(commitments.begin(), commitments.end(), std::back_inserter(v), - [](const std::pair& p) { return p.second; }); + 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); } } diff --git a/src/llmq/blockprocessor.h b/src/llmq/blockprocessor.h index 170e0007f742..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,13 +63,15 @@ 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; 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/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 b0097798e409..a0e6cf35958a 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -294,17 +294,17 @@ 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); - 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.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); 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