Skip to content

Commit 03fa115

Browse files
codablockUdjinM6
authored andcommitted
Speed up CQuorumManager::ScanQuorums (#2677)
* Store quorumHash of first mined commitment in evoDb This allows to skip scanning for quorums below this block. * Speed up CQuorumManager::ScanQuorums This does 2 things: 1. Only call HasQuorum for blocks that are potentially a quorumBlockHash These are only blocks which are at index 0 of each DKG interval 2. Stop scanning for quorums when we get below the first block that contained a commitment. If no commitment was ever mined, we bail out immediately. * Return result instead of {} * Remove HasQuorum() call as GetQuorum already does this * Remove unnecessary "if (!qc.IsNull()))" It's already checked at the top of the loop * When necessary, remove DB_FIRST_MINED_COMMITMENT from evoDb in UndoBlock
1 parent 3175526 commit 03fa115

File tree

3 files changed

+45
-13
lines changed

3 files changed

+45
-13
lines changed

src/llmq/quorums.cpp

+23-10
Original file line numberDiff line numberDiff line change
@@ -308,26 +308,39 @@ std::vector<CQuorumCPtr> CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp
308308
std::vector<CQuorumCPtr> CQuorumManager::ScanQuorums(Consensus::LLMQType llmqType, const uint256& startBlock, size_t maxCount)
309309
{
310310
std::vector<CQuorumCPtr> result;
311+
result.reserve(maxCount);
312+
313+
auto& params = Params().GetConsensus().llmqs.at(llmqType);
314+
315+
auto firstQuorumHash = quorumBlockProcessor->GetFirstMinedQuorumHash(llmqType);
316+
if (firstQuorumHash.IsNull()) {
317+
// no quorum mined yet, avoid scanning the whole chain down to genesis
318+
return result;
319+
}
311320

312321
LOCK(cs_main);
313322
if (!mapBlockIndex.count(startBlock)) {
314323
return result;
315324
}
316325

317-
result.reserve(maxCount);
318-
319326
CBlockIndex* pindex = mapBlockIndex[startBlock];
327+
pindex = chainActive[pindex->nHeight - (pindex->nHeight % params.dkgInterval)];
328+
329+
while (pindex != nullptr
330+
&& pindex->nHeight >= params.dkgInterval
331+
&& result.size() < maxCount
332+
&& deterministicMNManager->IsDIP3Enforced(pindex->nHeight)) {
333+
auto quorum = GetQuorum(llmqType, pindex->GetBlockHash());
334+
if (quorum) {
335+
result.emplace_back(quorum);
336+
}
320337

321-
while (pindex != NULL && result.size() < maxCount && deterministicMNManager->IsDIP3Enforced(pindex->nHeight)) {
322-
if (HasQuorum(llmqType, pindex->GetBlockHash())) {
323-
auto quorum = GetQuorum(llmqType, pindex->GetBlockHash());
324-
if (quorum) {
325-
result.emplace_back(quorum);
326-
}
338+
if (pindex->GetBlockHash() == firstQuorumHash) {
339+
// no need to scan further if we know that there are no quorums below this block
340+
break;
327341
}
328342

329-
// TODO speedup (skip blocks where no quorums could have been mined)
330-
pindex = pindex->pprev;
343+
pindex = pindex->GetAncestor(pindex->nHeight - params.dkgInterval);
331344
}
332345

333346
return result;

src/llmq/quorums_blockprocessor.cpp

+20-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace llmq
2323
CQuorumBlockProcessor* quorumBlockProcessor;
2424

2525
static const std::string DB_MINED_COMMITMENT = "q_mc";
26+
static const std::string DB_FIRST_MINED_COMMITMENT = "q_fmc";
2627

2728
void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
2829
{
@@ -188,6 +189,9 @@ bool CQuorumBlockProcessor::ProcessCommitment(const CBlockIndex* pindex, const C
188189

189190
// Store commitment in DB
190191
evoDb.Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair((uint8_t)params.type, quorumHash)), qc);
192+
if (!evoDb.Exists(std::make_pair(DB_FIRST_MINED_COMMITMENT, (uint8_t)params.type))) {
193+
evoDb.Write(std::make_pair(DB_FIRST_MINED_COMMITMENT, (uint8_t)params.type), quorumHash);
194+
}
191195

192196
LogPrintf("CQuorumBlockProcessor::%s -- processed commitment from block. type=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s\n", __func__,
193197
qc.llmqType, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString());
@@ -213,9 +217,12 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, const CBlockIndex* pi
213217

214218
evoDb.Erase(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(qc.llmqType, qc.quorumHash)));
215219

216-
if (!qc.IsNull()) {
217-
// if a reorg happened, we should allow to mine this commitment later
218-
AddMinableCommitment(qc);
220+
// if a reorg happened, we should allow to mine this commitment later
221+
AddMinableCommitment(qc);
222+
223+
uint256 fmq = GetFirstMinedQuorumHash(p.first);
224+
if (fmq == qc.quorumHash) {
225+
evoDb.Erase(std::make_pair(DB_FIRST_MINED_COMMITMENT, (uint8_t)p.first));
219226
}
220227
}
221228

@@ -306,6 +313,16 @@ bool CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, con
306313
return evoDb.Read(key, ret);
307314
}
308315

316+
uint256 CQuorumBlockProcessor::GetFirstMinedQuorumHash(Consensus::LLMQType llmqType)
317+
{
318+
auto key = std::make_pair(DB_FIRST_MINED_COMMITMENT, (uint8_t)llmqType);
319+
uint256 quorumHash;
320+
if (!evoDb.Read(key, quorumHash)) {
321+
return uint256();
322+
}
323+
return quorumHash;
324+
}
325+
309326
bool CQuorumBlockProcessor::HasMinableCommitment(const uint256& hash)
310327
{
311328
LOCK(minableCommitmentsCs);

src/llmq/quorums_blockprocessor.h

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class CQuorumBlockProcessor
4646
bool HasMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash);
4747
bool GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, CFinalCommitment& ret);
4848

49+
uint256 GetFirstMinedQuorumHash(Consensus::LLMQType llmqType);
50+
4951
private:
5052
bool GetCommitmentsFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, std::map<Consensus::LLMQType, CFinalCommitment>& ret, CValidationState& state);
5153
bool ProcessCommitment(const CBlockIndex* pindex, const CFinalCommitment& qc, CValidationState& state);

0 commit comments

Comments
 (0)