Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Improve quorum data caching and cleanup #5731

Merged
merged 10 commits into from
Nov 29, 2023
21 changes: 21 additions & 0 deletions src/llmq/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ struct LLMQParams {
// For rotated quorums it should be equal to 2 x active quorums set.
int keepOldConnections;

// The number of quorums for which we should keep keys. Usually it's equal to keepOldConnections.
// Unlike for other quorum types we want to keep data (secret key shares and vvec)
// for Platform quorums for much longer because Platform can be restarted and
// it must be able to re-sign stuff.

int keepOldKeys;

// How many members should we try to send all sigShares to before we give up.
int recoveryMembers;
};
Expand Down Expand Up @@ -138,6 +145,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 2, // just a few ones to allow easier testing

.keepOldConnections = 3,
.keepOldKeys = 3,
.recoveryMembers = 3,
},

Expand All @@ -163,6 +171,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 2, // just a few ones to allow easier testing

.keepOldConnections = 3,
.keepOldKeys = 3,
.recoveryMembers = 3,
},

Expand All @@ -188,6 +197,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 2, // just a few ones to allow easier testing

.keepOldConnections = 3,
.keepOldKeys = 3,
.recoveryMembers = 3,
},

Expand All @@ -213,6 +223,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 2, // just a few ones to allow easier testing

.keepOldConnections = 4,
.keepOldKeys = 4,
.recoveryMembers = 3,
},

Expand All @@ -238,6 +249,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 2, // just a few ones to allow easier testing

.keepOldConnections = 4,
.keepOldKeys = 24 * 30 * 2, // 2 months of quorums
.recoveryMembers = 3,
},

Expand All @@ -263,6 +275,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 4, // just a few ones to allow easier testing

.keepOldConnections = 5,
.keepOldKeys = 5,
.recoveryMembers = 6,
},

Expand All @@ -288,6 +301,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 2, // just a few ones to allow easier testing

.keepOldConnections = 4,
.keepOldKeys = 4,
.recoveryMembers = 4,
},

Expand All @@ -313,6 +327,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 4, // just a few ones to allow easier testing

.keepOldConnections = 5,
.keepOldKeys = 24 * 30 * 2, // 2 months of quorums
.recoveryMembers = 6,
},

Expand All @@ -338,6 +353,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {

.signingActiveQuorumCount = 24, // a full day worth of LLMQs
.keepOldConnections = 25,
.keepOldKeys = 25,
.recoveryMembers = 25,
},

Expand All @@ -363,6 +379,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {

.signingActiveQuorumCount = 32,
.keepOldConnections = 64,
.keepOldKeys = 64,
.recoveryMembers = 25,
},

Expand All @@ -389,6 +406,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 4, // two days worth of LLMQs

.keepOldConnections = 5,
.keepOldKeys = 5,
.recoveryMembers = 100,
},

Expand Down Expand Up @@ -416,6 +434,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 4, // four days worth of LLMQs

.keepOldConnections = 5,
.keepOldKeys = 5,
.recoveryMembers = 100,
},

Expand Down Expand Up @@ -443,6 +462,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 24, // a full day worth of LLMQs

.keepOldConnections = 25,
.keepOldKeys = 24 * 30 * 2, // 2 months of quorums
.recoveryMembers = 50,
},

Expand Down Expand Up @@ -470,6 +490,7 @@ static constexpr std::array<LLMQParams, 14> available_llmqs = {
.signingActiveQuorumCount = 24, // a full day worth of LLMQs

.keepOldConnections = 25,
.keepOldKeys = 24 * 30 * 2, // 2 months of quorums
.recoveryMembers = 12,
},

Expand Down
55 changes: 32 additions & 23 deletions src/llmq/quorums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ CQuorumManager::CQuorumManager(CBLSWorker& _blsWorker, CChainState& chainstate,
m_mn_sync(mn_sync),
m_peerman(peerman)
{
utils::InitQuorumsCache(mapQuorumsCache);
utils::InitQuorumsCache(scanQuorumsCache);
utils::InitQuorumsCache(mapQuorumsCache, false);
utils::InitQuorumsCache(scanQuorumsCache, false);

quorumThreadInterrupt.reset();
}
Expand Down Expand Up @@ -296,7 +296,7 @@ void CQuorumManager::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitial
}

TriggerQuorumDataRecoveryThreads(pindexNew);
CleanupOldQuorumData(pindexNew);
StartCleanupOldQuorumDataThread(pindexNew);
}

void CQuorumManager::CheckQuorumConnections(const Consensus::LLMQParams& llmqParams, const CBlockIndex* pindexNew) const
Expand Down Expand Up @@ -955,7 +955,7 @@ void CQuorumManager::StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, co
});
}

static void DataCleanupHelper(CDBWrapper& db, std::set<uint256> skip_list)
static void DataCleanupHelper(CDBWrapper& db, std::set<uint256> skip_list, bool compact = false)
{
const auto prefixes = {DB_QUORUM_QUORUM_VVEC, DB_QUORUM_SK_SHARE};

Expand Down Expand Up @@ -989,39 +989,48 @@ static void DataCleanupHelper(CDBWrapper& db, std::set<uint256> skip_list)

db.WriteBatch(batch);

LogPrint(BCLog::LLMQ, "CQuorumManager::%d -- %s removed %d\n", __func__, prefix, count);
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- %s removed %d\n", __func__, prefix, count);
}

pcursor.reset();
db.CompactFull();

if (compact) {
// Avoid using this on regular cleanups, use on db migrations only
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- compact start\n", __func__);
db.CompactFull();
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- compact end\n", __func__);
}
}

void CQuorumManager::CleanupOldQuorumData(const CBlockIndex* pIndex) const
void CQuorumManager::StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) const
{
if (!fMasternodeMode || pIndex == nullptr || (pIndex->nHeight % 576 != 0)) {
if (!fMasternodeMode || pIndex == nullptr || (pIndex->nHeight % 576 != 58 /* no DKGs running or to be started soon */)) {
UdjinM6 marked this conversation as resolved.
Show resolved Hide resolved
return;
}

std::set<uint256> dbKeysToSkip;
cxxtimer::Timer t(true);
knst marked this conversation as resolved.
Show resolved Hide resolved
LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- start\n", __func__);

LogPrint(BCLog::LLMQ, "CQuorumManager::%d -- start\n", __func__);
// Platform quorums in all networks are created every 24 blocks (~1h).
// Unlike for other quorum types we want to keep data (secret key shares and vvec)
// for Platform quorums for at least 2 months because Platform can be restarted and
// it must be able to re-sign stuff. During a month, 24 * 30 quorums are created.
constexpr auto numPlatformQuorumsDataToKeep = 24 * 30 * 2;
// do not block the caller thread
workerPool.push([pIndex, t, this](int threadId) {
std::set<uint256> dbKeysToSkip;

for (const auto& params : Params().GetConsensus().llmqs) {
auto nQuorumsToKeep = params.type == Params().GetConsensus().llmqTypePlatform ? numPlatformQuorumsDataToKeep : params.keepOldConnections;
const auto vecQuorums = ScanQuorums(params.type, pIndex, nQuorumsToKeep);
for (const auto& pQuorum : vecQuorums) {
dbKeysToSkip.insert(MakeQuorumKey(*pQuorum));
for (const auto& params : Params().GetConsensus().llmqs) {
if (quorumThreadInterrupt) {
break;
}
const auto vecQuorums = ScanQuorums(params.type, pIndex, params.keepOldKeys);
for (const auto& pQuorum : vecQuorums) {
UdjinM6 marked this conversation as resolved.
Show resolved Hide resolved
dbKeysToSkip.insert(MakeQuorumKey(*pQuorum));
}
}
}

DataCleanupHelper(m_evoDb.GetRawDB(), dbKeysToSkip);
if (!quorumThreadInterrupt) {
DataCleanupHelper(m_evoDb.GetRawDB(), dbKeysToSkip);
}

LogPrint(BCLog::LLMQ, "CQuorumManager::%d -- done\n", __func__);
LogPrint(BCLog::LLMQ, "CQuorumManager::StartCleanupOldQuorumDataThread -- done. time=%d\n", t.count());
});
}

} // namespace llmq
2 changes: 1 addition & 1 deletion src/llmq/quorums.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class CQuorumManager
void StartCachePopulatorThread(const CQuorumCPtr pQuorum) const;
void StartQuorumDataRecoveryThread(const CQuorumCPtr pQuorum, const CBlockIndex* pIndex, uint16_t nDataMask) const;

void CleanupOldQuorumData(const CBlockIndex* pIndex) const;
void StartCleanupOldQuorumDataThread(const CBlockIndex* pIndex) const;
};

extern std::unique_ptr<CQuorumManager> quorumManager;
Expand Down
12 changes: 6 additions & 6 deletions src/llmq/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1085,17 +1085,17 @@ std::map<Consensus::LLMQType, QvvecSyncMode> GetEnabledQuorumVvecSyncEntries()
}

template <typename CacheType>
void InitQuorumsCache(CacheType& cache)
void InitQuorumsCache(CacheType& cache, bool limit_by_connections)
{
for (const auto& llmq : Params().GetConsensus().llmqs) {
cache.emplace(std::piecewise_construct, std::forward_as_tuple(llmq.type),
std::forward_as_tuple(llmq.keepOldConnections));
std::forward_as_tuple(limit_by_connections ? llmq.keepOldConnections : llmq.keepOldKeys));
}
}
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, bool, StaticSaltedHasher>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, bool, StaticSaltedHasher>>& cache);
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::vector<CQuorumCPtr>, StaticSaltedHasher>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::vector<CQuorumCPtr>, StaticSaltedHasher>>& cache);
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>, std::less<Consensus::LLMQType>, std::allocator<std::pair<Consensus::LLMQType const, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>>>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>, std::less<Consensus::LLMQType>, std::allocator<std::pair<Consensus::LLMQType const, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>>>>&);
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, int, StaticSaltedHasher>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, int, StaticSaltedHasher>>& cache);
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, bool, StaticSaltedHasher>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, bool, StaticSaltedHasher>>& cache, bool limit_by_connections);
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::vector<CQuorumCPtr>, StaticSaltedHasher>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::vector<CQuorumCPtr>, StaticSaltedHasher>>& cache, bool limit_by_connections);
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>, std::less<Consensus::LLMQType>, std::allocator<std::pair<Consensus::LLMQType const, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>>>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>, std::less<Consensus::LLMQType>, std::allocator<std::pair<Consensus::LLMQType const, unordered_lru_cache<uint256, std::shared_ptr<llmq::CQuorum>, StaticSaltedHasher, 0ul, 0ul>>>>&cache, bool limit_by_connections);
template void InitQuorumsCache<std::map<Consensus::LLMQType, unordered_lru_cache<uint256, int, StaticSaltedHasher>>>(std::map<Consensus::LLMQType, unordered_lru_cache<uint256, int, StaticSaltedHasher>>& cache, bool limit_by_connections);

} // namespace utils

Expand Down
2 changes: 1 addition & 1 deletion src/llmq/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void IterateNodesRandom(NodesContainer& nodeStates, Continue&& cont, Callback&&
}

template <typename CacheType>
void InitQuorumsCache(CacheType& cache);
void InitQuorumsCache(CacheType& cache, bool limit_by_connections = true);

} // namespace utils

Expand Down
Loading