@@ -566,11 +566,15 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
566566 diff = oldList.BuildDiff (newList);
567567
568568 evoDb.Write (std::make_pair (DB_LIST_DIFF, newList.GetBlockHash ()), diff);
569- if ((nHeight % SNAPSHOT_LIST_PERIOD ) == 0 || oldList.GetHeight () == -1 ) {
569+ if ((nHeight % DISK_SNAPSHOT_PERIOD ) == 0 || oldList.GetHeight () == -1 ) {
570570 evoDb.Write (std::make_pair (DB_LIST_SNAPSHOT, newList.GetBlockHash ()), newList);
571+ mnListsCache.emplace (newList.GetBlockHash (), newList);
571572 LogPrintf (" CDeterministicMNManager::%s -- Wrote snapshot. nHeight=%d, mapCurMNs.allMNsCount=%d\n " ,
572573 __func__, nHeight, newList.GetAllMNsCount ());
573574 }
575+
576+ diff.nHeight = pindex->nHeight ;
577+ mnListDiffsCache.emplace (pindex->GetBlockHash (), diff);
574578 } catch (const std::exception& e) {
575579 LogPrintf (" CDeterministicMNManager::%s -- internal error: %s\n " , __func__, e.what ());
576580 return _state.DoS (100 , false , REJECT_INVALID, " failed-dmn-block" );
@@ -616,6 +620,7 @@ bool CDeterministicMNManager::UndoBlock(const CBlock& block, const CBlockIndex*
616620 }
617621
618622 mnListsCache.erase (blockHash);
623+ mnListDiffsCache.erase (blockHash);
619624 }
620625
621626 if (diff.HasChanges ()) {
@@ -918,13 +923,13 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const CBlockIndex*
918923 LOCK (cs);
919924
920925 CDeterministicMNList snapshot;
921- std::list<std::pair< const CBlockIndex*, CDeterministicMNListDiff>> listDiff ;
926+ std::list<const CBlockIndex*> listDiffIndexes ;
922927
923928 while (true ) {
924929 // try using cache before reading from disk
925- auto it = mnListsCache.find (pindex->GetBlockHash ());
926- if (it != mnListsCache.end ()) {
927- snapshot = it ->second ;
930+ auto itLists = mnListsCache.find (pindex->GetBlockHash ());
931+ if (itLists != mnListsCache.end ()) {
932+ snapshot = itLists ->second ;
928933 break ;
929934 }
930935
@@ -933,28 +938,51 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const CBlockIndex*
933938 break ;
934939 }
935940
941+ // no snapshot found yet, check diffs
942+ auto itDiffs = mnListDiffsCache.find (pindex->GetBlockHash ());
943+ if (itDiffs != mnListDiffsCache.end ()) {
944+ listDiffIndexes.emplace_front (pindex);
945+ pindex = pindex->pprev ;
946+ continue ;
947+ }
948+
936949 CDeterministicMNListDiff diff;
937950 if (!evoDb.Read (std::make_pair (DB_LIST_DIFF, pindex->GetBlockHash ()), diff)) {
951+ // no snapshot and no diff on disk means that it's the initial snapshot
938952 snapshot = CDeterministicMNList (pindex->GetBlockHash (), -1 , 0 );
939953 mnListsCache.emplace (pindex->GetBlockHash (), snapshot);
940954 break ;
941955 }
942956
943- listDiff.emplace_front (pindex, std::move (diff));
957+ diff.nHeight = pindex->nHeight ;
958+ mnListDiffsCache.emplace (pindex->GetBlockHash (), std::move (diff));
959+ listDiffIndexes.emplace_front (pindex);
944960 pindex = pindex->pprev ;
945961 }
946962
947- for (const auto & p : listDiff) {
948- auto diffIndex = p.first ;
949- auto & diff = p.second ;
963+ for (const auto & diffIndex : listDiffIndexes) {
964+ const auto & diff = mnListDiffsCache.at (diffIndex->GetBlockHash ());
950965 if (diff.HasChanges ()) {
951966 snapshot = snapshot.ApplyDiff (diffIndex, diff);
952967 } else {
953968 snapshot.SetBlockHash (diffIndex->GetBlockHash ());
954969 snapshot.SetHeight (diffIndex->nHeight );
955970 }
971+ }
956972
957- mnListsCache.emplace (diffIndex->GetBlockHash (), snapshot);
973+ if (tipIndex) {
974+ // always keep a snapshot for the tip
975+ if (snapshot.GetBlockHash () == tipIndex->GetBlockHash ()) {
976+ mnListsCache.emplace (snapshot.GetBlockHash (), snapshot);
977+ } else {
978+ // keep snapshots for yet alive quorums
979+ for (auto & p_llmq : Params ().GetConsensus ().llmqs ) {
980+ if ((snapshot.GetHeight () % p_llmq.second .dkgInterval == 0 ) && (snapshot.GetHeight () + p_llmq.second .dkgInterval * (p_llmq.second .keepOldConnections + 1 ) >= tipIndex->nHeight )) {
981+ mnListsCache.emplace (snapshot.GetBlockHash (), snapshot);
982+ break ;
983+ }
984+ }
985+ }
958986 }
959987
960988 return snapshot;
@@ -1006,15 +1034,47 @@ void CDeterministicMNManager::CleanupCache(int nHeight)
10061034{
10071035 AssertLockHeld (cs);
10081036
1009- std::vector<uint256> toDelete;
1037+ std::vector<uint256> toDeleteLists;
1038+ std::vector<uint256> toDeleteDiffs;
10101039 for (const auto & p : mnListsCache) {
1011- if (p.second .GetHeight () + LISTS_CACHE_SIZE < nHeight) {
1012- toDelete.emplace_back (p.first );
1040+ if (p.second .GetHeight () + LIST_DIFFS_CACHE_SIZE < nHeight) {
1041+ toDeleteLists.emplace_back (p.first );
1042+ continue ;
1043+ }
1044+ bool fQuorumCache {false };
1045+ for (auto & p_llmq : Params ().GetConsensus ().llmqs ) {
1046+ if ((p.second .GetHeight () % p_llmq.second .dkgInterval == 0 ) && (p.second .GetHeight () + p_llmq.second .dkgInterval * (p_llmq.second .keepOldConnections + 1 ) >= nHeight)) {
1047+ fQuorumCache = true ;
1048+ break ;
1049+ }
1050+ }
1051+ if (fQuorumCache ) {
1052+ // at least one quorum could be using it, keep it
1053+ continue ;
1054+ }
1055+ // no alive quorums using it, see if it was a cache for the tip or for a now outdated quorum
1056+ if (tipIndex && tipIndex->pprev && (p.first == tipIndex->pprev ->GetBlockHash ())) {
1057+ toDeleteLists.emplace_back (p.first );
1058+ } else {
1059+ for (auto & p_llmq : Params ().GetConsensus ().llmqs ) {
1060+ if (p.second .GetHeight () % p_llmq.second .dkgInterval == 0 ) {
1061+ toDeleteLists.emplace_back (p.first );
1062+ break ;
1063+ }
1064+ }
10131065 }
10141066 }
1015- for (const auto & h : toDelete ) {
1067+ for (const auto & h : toDeleteLists ) {
10161068 mnListsCache.erase (h);
10171069 }
1070+ for (const auto & p : mnListDiffsCache) {
1071+ if (p.second .nHeight + LIST_DIFFS_CACHE_SIZE < nHeight) {
1072+ toDeleteDiffs.emplace_back (p.first );
1073+ }
1074+ }
1075+ for (const auto & h : toDeleteDiffs) {
1076+ mnListDiffsCache.erase (h);
1077+ }
10181078}
10191079
10201080bool CDeterministicMNManager::UpgradeDiff (CDBBatch& batch, const CBlockIndex* pindexNext, const CDeterministicMNList& curMNList, CDeterministicMNList& newMNList)
@@ -1111,7 +1171,7 @@ void CDeterministicMNManager::UpgradeDBIfNeeded()
11111171 CDeterministicMNList newMNList;
11121172 UpgradeDiff (batch, pindex, curMNList, newMNList);
11131173
1114- if ((nHeight % SNAPSHOT_LIST_PERIOD ) == 0 ) {
1174+ if ((nHeight % DISK_SNAPSHOT_PERIOD ) == 0 ) {
11151175 batch.Write (std::make_pair (DB_LIST_SNAPSHOT, pindex->GetBlockHash ()), newMNList);
11161176 evoDb.GetRawDB ().WriteBatch (batch);
11171177 batch.Clear ();
0 commit comments