Skip to content

Commit 0762074

Browse files
committed
Implement GetMined(AndActive)CommitmentsUntilBlock and use it in ScanQuorums
This fixes a bug in ScanQuorums which made it return quorums which were not mined at the time of pindexStart. This was due to quorumHashes being based on older blocks (the phase=0 block) which are ancestors of pindexStart even if the commitment was actually mined in a later block. GetMinedAndActiveCommitmentsUntilBlock is also going to be used for quorum commitment merkle roots in CCbTx. This also removes GetFirstMinedQuorumHash as it's not needed anymore.
1 parent d5250a3 commit 0762074

File tree

4 files changed

+68
-37
lines changed

4 files changed

+68
-37
lines changed

src/evo/evodb.h

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class CEvoDB
3535
return t;
3636
}
3737

38+
CurTransaction& GetCurTransaction()
39+
{
40+
return curDBTransaction;
41+
}
42+
3843
template <typename K, typename V>
3944
bool Read(const K& key, V& value)
4045
{

src/llmq/quorums.cpp

+8-24
Original file line numberDiff line numberDiff line change
@@ -300,34 +300,18 @@ std::vector<CQuorumCPtr> CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp
300300

301301
std::vector<CQuorumCPtr> CQuorumManager::ScanQuorums(Consensus::LLMQType llmqType, const CBlockIndex* pindexStart, size_t maxCount)
302302
{
303-
std::vector<CQuorumCPtr> result;
304-
result.reserve(maxCount);
305-
306303
auto& params = Params().GetConsensus().llmqs.at(llmqType);
307304

308-
auto firstQuorumHash = quorumBlockProcessor->GetFirstMinedQuorumHash(llmqType);
309-
if (firstQuorumHash.IsNull()) {
310-
// no quorum mined yet, avoid scanning the whole chain down to genesis
311-
return result;
312-
}
313-
314-
auto pindex = pindexStart->GetAncestor(pindexStart->nHeight - (pindexStart->nHeight % params.dkgInterval));
305+
auto quorumIndexes = quorumBlockProcessor->GetMinedCommitmentsUntilBlock(params.type, pindexStart, maxCount);
315306

316-
while (pindex != nullptr
317-
&& pindex->nHeight >= params.dkgInterval
318-
&& result.size() < maxCount
319-
&& deterministicMNManager->IsDIP3Enforced(pindex->nHeight)) {
320-
auto quorum = GetQuorum(llmqType, pindex);
321-
if (quorum) {
322-
result.emplace_back(quorum);
323-
}
324-
325-
if (pindex->GetBlockHash() == firstQuorumHash) {
326-
// no need to scan further if we know that there are no quorums below this block
327-
break;
328-
}
307+
std::vector<CQuorumCPtr> result;
308+
result.reserve(quorumIndexes.size());
329309

330-
pindex = pindex->GetAncestor(pindex->nHeight - params.dkgInterval);
310+
for (auto& quorumIndex : quorumIndexes) {
311+
assert(quorumIndex);
312+
auto quorum = GetQuorum(params.type, quorumIndex);
313+
assert(quorum != nullptr);
314+
result.emplace_back(quorum);
331315
}
332316

333317
return result;

src/llmq/quorums_blockprocessor.cpp

+53-12
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ 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";
2726
static const std::string DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT = "q_mcih";
2827

2928
static const std::string DB_UPGRADED = "q_dbupgraded";
@@ -244,11 +243,6 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, const CBlockIndex* pi
244243

245244
// if a reorg happened, we should allow to mine this commitment later
246245
AddMinableCommitment(qc);
247-
248-
uint256 fmq = GetFirstMinedQuorumHash(p.first);
249-
if (fmq == qc.quorumHash) {
250-
evoDb.Erase(std::make_pair(DB_FIRST_MINED_COMMITMENT, (uint8_t)p.first));
251-
}
252246
}
253247

254248
return true;
@@ -392,14 +386,61 @@ bool CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, con
392386
return evoDb.Read(key, ret);
393387
}
394388

395-
uint256 CQuorumBlockProcessor::GetFirstMinedQuorumHash(Consensus::LLMQType llmqType)
389+
std::vector<const CBlockIndex*> CQuorumBlockProcessor::GetMinedCommitmentsUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t maxCount)
396390
{
397-
auto key = std::make_pair(DB_FIRST_MINED_COMMITMENT, (uint8_t)llmqType);
398-
uint256 quorumHash;
399-
if (!evoDb.Read(key, quorumHash)) {
400-
return uint256();
391+
auto dbIt = evoDb.GetCurTransaction().NewIteratorUniquePtr();
392+
393+
auto firstKey = BuildInversedHeightKey(llmqType, pindex->nHeight);
394+
auto lastKey = BuildInversedHeightKey(llmqType, 0);
395+
396+
dbIt->Seek(firstKey);
397+
398+
std::vector<const CBlockIndex*> ret;
399+
ret.reserve(maxCount);
400+
401+
while (dbIt->Valid() && ret.size() < maxCount) {
402+
decltype(firstKey) curKey;
403+
int quorumHeight;
404+
if (!dbIt->GetKey(curKey) || curKey >= lastKey) {
405+
break;
406+
}
407+
if (std::get<0>(curKey) != DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT || std::get<1>(curKey) != (uint8_t)llmqType) {
408+
break;
409+
}
410+
411+
int nMinedHeight = std::numeric_limits<int>::max() - std::get<2>(curKey);
412+
if (nMinedHeight > pindex->nHeight) {
413+
break;
414+
}
415+
416+
if (!dbIt->GetValue(quorumHeight)) {
417+
break;
418+
}
419+
420+
auto quorumIndex = pindex->GetAncestor(quorumHeight);
421+
assert(quorumIndex);
422+
ret.emplace_back(pindex->GetAncestor(quorumHeight));
423+
424+
dbIt->Next();
401425
}
402-
return quorumHash;
426+
427+
return ret;
428+
}
429+
430+
std::map<Consensus::LLMQType, std::vector<const CBlockIndex*>> CQuorumBlockProcessor::GetMinedAndActiveCommitmentsUntilBlock(const CBlockIndex* pindex)
431+
{
432+
std::map<Consensus::LLMQType, std::vector<const CBlockIndex*>> ret;
433+
434+
for (const auto& p : Params().GetConsensus().llmqs) {
435+
auto& v = ret[p.second.type];
436+
v.reserve(p.second.signingActiveQuorumCount);
437+
auto commitments = GetMinedCommitmentsUntilBlock(p.second.type, pindex, p.second.signingActiveQuorumCount);
438+
for (auto& c : commitments) {
439+
v.emplace_back(c);
440+
}
441+
}
442+
443+
return ret;
403444
}
404445

405446
bool CQuorumBlockProcessor::HasMinableCommitment(const uint256& hash)

src/llmq/quorums_blockprocessor.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ class CQuorumBlockProcessor
5353
bool HasMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash);
5454
bool GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, CFinalCommitment& ret);
5555

56-
uint256 GetFirstMinedQuorumHash(Consensus::LLMQType llmqType);
56+
std::vector<const CBlockIndex*> GetMinedCommitmentsUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t maxCount);
57+
std::map<Consensus::LLMQType, std::vector<const CBlockIndex*>> GetMinedAndActiveCommitmentsUntilBlock(const CBlockIndex* pindex);
5758

5859
private:
5960
bool GetCommitmentsFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, std::map<Consensus::LLMQType, CFinalCommitment>& ret, CValidationState& state);

0 commit comments

Comments
 (0)