llmq: Various fixes and improvements (#4890)

* feat(llmq): Introduce useRotation in LLMQParams

* fix(llmq): Fix IsQuorumRotationEnabled to recognize all dip0024 quorums

* fix(llmq): Do not allow rotation llmqs for `-llmqinstantsend` and non-rotation ones for `-llmqinstantsenddip0024`

* fix(llmq): Unify and fix IsMiningPhase

NOTE: no need for 1 extra block in mining phase for rotation quorums

* chore(llmq): Reduce the number of IsQuorumRotationEnabled calls

* chore(llmq): Improve logging

* feat(llmq): Make `llmq-` threads for rotation quorums distinguishable by quorum index

* fix(llmq): Fix another endless loop in GetQuorumRelayMembers

* throw an error when a llmq type with an incompatible rotation flag is picked for `-llmq...` params

* Add a note about loop conditions

* llmq: Make TransactionRemovedFromMempool the last action for invalid txes, just like we do for orphans with rejected parents

Write to log, send reject msg and (maybe) punish first and only then notify IS about the tx removal. Makes it easier to reason about it when reading logs.
This commit is contained in:
UdjinM6 2022-06-27 13:02:46 +03:00 committed by pasta
parent 2dcbedd6e2
commit 9b0222a01a
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
7 changed files with 81 additions and 59 deletions

View File

@ -1223,6 +1223,9 @@ void CDevNetParams::UpdateDevnetLLMQChainLocksFromArgs(const ArgsManager& args)
Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE;
for (const auto& params : consensus.llmqs) {
if (params.name == strLLMQType) {
if (params.useRotation) {
throw std::runtime_error("LLMQ type specified for -llmqchainlocks must NOT use rotation");
}
llmqType = params.type;
}
}
@ -1242,6 +1245,9 @@ void CDevNetParams::UpdateDevnetLLMQInstantSendFromArgs(const ArgsManager& args)
Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE;
for (const auto& params : consensus.llmqs) {
if (params.name == strLLMQType) {
if (params.useRotation) {
throw std::runtime_error("LLMQ type specified for -llmqinstantsend must NOT use rotation");
}
llmqType = params.type;
}
}
@ -1261,6 +1267,9 @@ void CDevNetParams::UpdateDevnetLLMQInstantSendDIP0024FromArgs(const ArgsManager
Consensus::LLMQType llmqType = Consensus::LLMQType::LLMQ_NONE;
for (const auto& params : consensus.llmqs) {
if (params.name == strLLMQType) {
if (!params.useRotation) {
throw std::runtime_error("LLMQ type specified for -llmqinstantsenddip0024 must use rotation");
}
llmqType = params.type;
}
}

View File

@ -252,7 +252,9 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH
return true;
}
if (llmq::CLLMQUtils::IsQuorumRotationEnabled(llmq_params.type, pQuorumBaseBlockIndex)) {
bool rotation_enabled = CLLMQUtils::IsQuorumRotationEnabled(llmq_params.type, pQuorumBaseBlockIndex);
if (rotation_enabled) {
LogPrint(BCLog::LLMQ, "[ProcessCommitment] height[%d] pQuorumBaseBlockIndex[%d] quorumIndex[%d] qversion[%d] Built\n",
nHeight, pQuorumBaseBlockIndex->nHeight, qc.quorumIndex, qc.nVersion);
}
@ -261,7 +263,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH
auto cacheKey = std::make_pair(llmq_params.type, quorumHash);
evoDb.Write(std::make_pair(DB_MINED_COMMITMENT, cacheKey), std::make_pair(qc, blockHash));
if (llmq::CLLMQUtils::IsQuorumRotationEnabled(llmq_params.type, pQuorumBaseBlockIndex)) {
if (rotation_enabled) {
evoDb.Write(BuildInversedHeightKeyIndexed(llmq_params.type, nHeight, int(qc.quorumIndex)), pQuorumBaseBlockIndex->nHeight);
} else {
evoDb.Write(BuildInversedHeightKey(llmq_params.type, nHeight), pQuorumBaseBlockIndex->nHeight);
@ -415,23 +417,16 @@ bool CQuorumBlockProcessor::IsMiningPhase(const Consensus::LLMQParams& llmqParam
// Note: This function can be called for new blocks
assert(nHeight <= ::ChainActive().Height() + 1);
const auto pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight);
if (CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) {
int quorumCycleStartHeight = nHeight - (nHeight % llmqParams.dkgInterval);
int quorumCycleMiningStartHeight = quorumCycleStartHeight + llmqParams.signingActiveQuorumCount + (5 * llmqParams.dkgPhaseBlocks) + 1;
int quorumCycleMiningEndHeight = quorumCycleMiningStartHeight + (llmqParams.dkgMiningWindowEnd - llmqParams.dkgMiningWindowStart);
LogPrint(BCLog::LLMQ, "[IsMiningPhase] nHeight[%d] quorumCycleStartHeight[%d] -- mining[%d-%d]\n", nHeight, quorumCycleStartHeight, quorumCycleMiningStartHeight, quorumCycleMiningEndHeight);
int quorumCycleStartHeight = nHeight - (nHeight % llmqParams.dkgInterval);
int quorumCycleMiningStartHeight = quorumCycleStartHeight + llmqParams.dkgMiningWindowStart;
int quorumCycleMiningEndHeight = quorumCycleStartHeight + llmqParams.dkgMiningWindowEnd;
if (nHeight >= quorumCycleMiningStartHeight && nHeight <= quorumCycleMiningEndHeight) {
return true;
}
} else {
int phaseIndex = nHeight % llmqParams.dkgInterval;
if (phaseIndex >= llmqParams.dkgMiningWindowStart && phaseIndex <= llmqParams.dkgMiningWindowEnd) {
return true;
}
if (nHeight >= quorumCycleMiningStartHeight && nHeight <= quorumCycleMiningEndHeight) {
LogPrint(BCLog::LLMQ, "[IsMiningPhase] nHeight[%d] llmqType[%d] quorumCycleStartHeight[%d] -- mining[%d-%d]\n", nHeight, int(llmqParams.type), quorumCycleStartHeight, quorumCycleMiningStartHeight, quorumCycleMiningEndHeight);
return true;
}
LogPrint(BCLog::LLMQ, "[IsMiningPhase] nHeight[%d] llmqType[%d] quorumCycleStartHeight[%d] -- NOT mining[%d-%d]\n", nHeight, int(llmqParams.type), quorumCycleStartHeight, quorumCycleMiningStartHeight, quorumCycleMiningEndHeight);
return false;
}
@ -446,13 +441,13 @@ bool CQuorumBlockProcessor::IsCommitmentRequired(const Consensus::LLMQParams& ll
assert(nHeight <= ::ChainActive().Height() + 1);
const auto pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight);
for (int quorumIndex = 0; quorumIndex < llmqParams.signingActiveQuorumCount; ++quorumIndex) {
bool rotation_enabled = CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex);
size_t quorums_num = rotation_enabled ? llmqParams.signingActiveQuorumCount : 1;
for (int quorumIndex = 0; quorumIndex < quorums_num; ++quorumIndex) {
uint256 quorumHash = GetQuorumBlockHash(llmqParams, nHeight, quorumIndex);
if (quorumHash.IsNull()) return false;
if (HasMinedCommitment(llmqParams.type, quorumHash)) return false;
if (!CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) {
break;
}
}
return true;
@ -725,8 +720,11 @@ std::optional<std::vector<CFinalCommitment>> CQuorumBlockProcessor::GetMineableC
assert(nHeight <= ::ChainActive().Height() + 1);
const auto pindex = ::ChainActive().Height() < nHeight ? ::ChainActive().Tip() : ::ChainActive().Tip()->GetAncestor(nHeight);
bool rotation_enabled = CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex);
size_t quorums_num = rotation_enabled ? llmqParams.signingActiveQuorumCount : 1;
std::stringstream ss;
for (int quorumIndex = 0; quorumIndex < llmqParams.signingActiveQuorumCount; ++quorumIndex) {
for (int quorumIndex = 0; quorumIndex < quorums_num; ++quorumIndex) {
CFinalCommitment cf;
uint256 quorumHash = GetQuorumBlockHash(llmqParams, nHeight, quorumIndex);
@ -742,7 +740,7 @@ std::optional<std::vector<CFinalCommitment>> CQuorumBlockProcessor::GetMineableC
// null commitment required
cf = CFinalCommitment(llmqParams, quorumHash);
cf.quorumIndex = static_cast<int16_t>(quorumIndex);
if (CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) {
if (rotation_enabled) {
cf.nVersion = CFinalCommitment::INDEXED_QUORUM_VERSION;
}
ss << "{ created nversion[" << cf.nVersion << "] quorumIndex[" << cf.quorumIndex << "] }";
@ -752,9 +750,6 @@ std::optional<std::vector<CFinalCommitment>> CQuorumBlockProcessor::GetMineableC
}
ret.push_back(std::move(cf));
if (!CLLMQUtils::IsQuorumRotationEnabled(llmqParams.type, pindex)) {
break;
}
}
LogPrint(BCLog::LLMQ, "GetMineableCommitments cf height[%d] content: %s\n", nHeight, ss.str());

View File

@ -102,7 +102,7 @@ void CDKGSessionHandler::UpdatedBlockTip(const CBlockIndex* pindexNew)
phase = static_cast<QuorumPhase>(phaseInt);
}
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s - quorumIndex=%d, currentHeight=%d, pQuorumBaseBlockIndex->nHeight=%d, oldPhase=%d, newPhase=%d\n", __func__,
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s qi[%d] currentHeight=%d, pQuorumBaseBlockIndex->nHeight=%d, oldPhase=%d, newPhase=%d\n", __func__,
params.name, quorumIndex, currentHeight, pQuorumBaseBlockIndex->nHeight, int(oldPhase), int(phase));
}
@ -126,7 +126,7 @@ void CDKGSessionHandler::StartThread()
throw std::runtime_error("Tried to start an already started CDKGSessionHandler thread.");
}
std::string threadName = strprintf("llmq-%d", (uint8_t)params.type);
std::string threadName = strprintf("llmq-%d-%d", (uint8_t)params.type, quorumIndex);
phaseHandlerThread = std::thread(&TraceThread<std::function<void()> >, threadName, std::function<void()>(std::bind(&CDKGSessionHandler::PhaseHandlerThread, this)));
}
@ -148,10 +148,10 @@ bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pQuorumBaseBlockIndex)
auto mns = CLLMQUtils::GetAllQuorumMembers(params.type, pQuorumBaseBlockIndex);
if (!curSession->Init(pQuorumBaseBlockIndex, mns, WITH_LOCK(activeMasternodeInfoCs, return activeMasternodeInfo.proTxHash), quorumIndex)) {
LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, mns.size());
LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization failed for %s qi[%d] mns[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex, mns.size());
return false;
} else {
LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization OK for %s\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name);
LogPrintf("CDKGSessionManager::%s -- height[%d] quorum initialization OK for %s qi[%d]\n", __func__, pQuorumBaseBlockIndex->nHeight, curSession->params.name, quorumIndex);
}
return true;
@ -171,23 +171,23 @@ void CDKGSessionHandler::WaitForNextPhase(std::optional<QuorumPhase> curPhase,
const uint256& expectedQuorumHash,
const WhileWaitFunc& shouldNotWait) const
{
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase));
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase));
while (true) {
if (stopRequested) {
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due to stop/shutdown requested\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex);
throw AbortPhaseException();
}
auto [_phase, _quorumHash] = GetPhaseAndQuorumHash();
if (!expectedQuorumHash.IsNull() && _quorumHash != expectedQuorumHash) {
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due unexpected expectedQuorumHash change\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected expectedQuorumHash change\n", __func__, params.name, quorumIndex);
throw AbortPhaseException();
}
if (_phase == nextPhase) {
break;
}
if (curPhase.has_value() && _phase != curPhase) {
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due unexpected phase change\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected phase change, _phase=%d, curPhase=%d\n", __func__, params.name, quorumIndex, int(_phase), curPhase.has_value() ? int(*curPhase) : -1);
throw AbortPhaseException();
}
if (!shouldNotWait()) {
@ -195,7 +195,7 @@ void CDKGSessionHandler::WaitForNextPhase(std::optional<QuorumPhase> curPhase,
}
}
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase));
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, curPhase.has_value() ? int(*curPhase) : -1, int(nextPhase));
if (nextPhase == QuorumPhase::Initialized) {
quorumDKGDebugManager->ResetLocalSessionStatus(params.type, quorumIndex);
@ -210,21 +210,21 @@ void CDKGSessionHandler::WaitForNextPhase(std::optional<QuorumPhase> curPhase,
void CDKGSessionHandler::WaitForNewQuorum(const uint256& oldQuorumHash) const
{
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d]- starting\n", __func__, params.name, quorumIndex);
while (true) {
if (stopRequested) {
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due to stop/shutdown requested\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex);
throw AbortPhaseException();
}
auto p = GetPhaseAndQuorumHash();
if (p.second != oldQuorumHash) {
auto [_, _quorumHash] = GetPhaseAndQuorumHash();
if (_quorumHash != oldQuorumHash) {
break;
}
UninterruptibleSleep(std::chrono::milliseconds{100});
}
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done\n", __func__, params.name, quorumIndex);
}
// Sleep some time to not fully overload the whole network
@ -263,11 +263,11 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase,
heightTmp = heightStart = currentHeight;
}
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting sleep for %d ms, curPhase=%d\n", __func__, params.name, sleepTime, int(curPhase));
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting sleep for %d ms, curPhase=%d\n", __func__, params.name, quorumIndex, sleepTime, int(curPhase));
while (GetTimeMillis() < endTime) {
if (stopRequested) {
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due to stop/shutdown requested\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due to stop/shutdown requested\n", __func__, params.name, quorumIndex);
throw AbortPhaseException();
}
{
@ -283,7 +283,7 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase,
}
if (phase != curPhase || quorumHash != expectedQuorumHash) {
// Something went wrong and/or we missed quite a few blocks and it's just too late now
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - aborting due unexpected phase/expectedQuorumHash change\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - aborting due unexpected phase/expectedQuorumHash change\n", __func__, params.name, quorumIndex);
throw AbortPhaseException();
}
}
@ -292,7 +292,7 @@ void CDKGSessionHandler::SleepBeforePhase(QuorumPhase curPhase,
}
}
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done, curPhase=%d\n", __func__, params.name, int(curPhase));
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done, curPhase=%d\n", __func__, params.name, quorumIndex, int(curPhase));
}
void CDKGSessionHandler::HandlePhase(QuorumPhase curPhase,
@ -302,13 +302,13 @@ void CDKGSessionHandler::HandlePhase(QuorumPhase curPhase,
const StartPhaseFunc& startPhaseFunc,
const WhileWaitFunc& runWhileWaiting)
{
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, int(curPhase), int(nextPhase));
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - starting, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, int(curPhase), int(nextPhase));
SleepBeforePhase(curPhase, expectedQuorumHash, randomSleepFactor, runWhileWaiting);
startPhaseFunc();
WaitForNextPhase(curPhase, nextPhase, expectedQuorumHash, runWhileWaiting);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, int(curPhase), int(nextPhase));
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionManager::%s -- %s qi[%d] - done, curPhase=%d, nextPhase=%d\n", __func__, params.name, quorumIndex, int(curPhase), int(nextPhase));
}
// returns a set of NodeIds which sent invalid messages
@ -543,14 +543,14 @@ void CDKGSessionHandler::PhaseHandlerThread()
{
while (!stopRequested) {
try {
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s - starting HandleDKGRound\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s qi[%d] - starting HandleDKGRound\n", __func__, params.name, quorumIndex);
HandleDKGRound();
} catch (AbortPhaseException& e) {
quorumDKGDebugManager->UpdateLocalSessionStatus(params.type, quorumIndex, [&](CDKGDebugSessionStatus& status) {
status.aborted = true;
return true;
});
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s - aborted current DKG session\n", __func__, params.name);
LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- %s qi[%d] - aborted current DKG session\n", __func__, params.name, quorumIndex);
}
}
}

View File

@ -45,6 +45,9 @@ struct LLMQParams {
// not consensus critical, only used in logging, RPC and UI
std::string_view name;
// Whether this is a DIP0024 quorum or not
bool useRotation;
// the size of the quorum, e.g. 50 or 400
int size;
@ -113,6 +116,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_TEST,
.name = "llmq_test",
.useRotation = false,
.size = 3,
.minSize = 2,
.threshold = 2,
@ -137,6 +141,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_TEST_INSTANTSEND,
.name = "llmq_test_instantsend",
.useRotation = false,
.size = 3,
.minSize = 2,
.threshold = 2,
@ -161,6 +166,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_TEST_V17,
.name = "llmq_test_v17",
.useRotation = false,
.size = 3,
.minSize = 2,
.threshold = 2,
@ -185,14 +191,15 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_TEST_DIP0024,
.name = "llmq_test_dip0024",
.useRotation = true,
.size = 4,
.minSize = 3,
.threshold = 2,
.dkgInterval = 24, // DKG cycle
.dkgPhaseBlocks = 2,
.dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization
.dkgMiningWindowEnd = 18,
.dkgMiningWindowStart = 12, // signingActiveQuorumCount + dkgPhaseBlocks * 5 = after finalization
.dkgMiningWindowEnd = 20,
.dkgBadVotesThreshold = 2,
.signingActiveQuorumCount = 2, // just a few ones to allow easier testing
@ -209,6 +216,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_DEVNET,
.name = "llmq_devnet",
.useRotation = false,
.size = 12,
.minSize = 7,
.threshold = 6,
@ -259,6 +267,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_50_60,
.name = "llmq_50_60",
.useRotation = false,
.size = 50,
.minSize = 40,
.threshold = 30,
@ -283,14 +292,15 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_60_75,
.name = "llmq_60_75",
.useRotation = true,
.size = 60,
.minSize = 50,
.threshold = 45,
.dkgInterval = 24 * 12, // DKG cycle every 12 hours
.dkgPhaseBlocks = 2,
.dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization
.dkgMiningWindowEnd = 18,
.dkgMiningWindowStart = 42, // signingActiveQuorumCount + dkgPhaseBlocks * 5 = after finalization
.dkgMiningWindowEnd = 50,
.dkgBadVotesThreshold = 48,
.signingActiveQuorumCount = 32,
@ -307,6 +317,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_400_60,
.name = "llmq_400_60",
.useRotation = false,
.size = 400,
.minSize = 300,
.threshold = 240,
@ -333,6 +344,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_400_85,
.name = "llmq_400_85",
.useRotation = false,
.size = 400,
.minSize = 350,
.threshold = 340,
@ -359,6 +371,7 @@ static constexpr std::array<LLMQParams, 11> available_llmqs = {
LLMQParams{
.type = LLMQType::LLMQ_100_67,
.name = "llmq_100_67",
.useRotation = false,
.size = 100,
.minSize = 80,
.threshold = 67,

View File

@ -534,7 +534,7 @@ bool CLLMQUtils::IsQuorumRotationEnabled(Consensus::LLMQType llmqType, const CBl
{
assert(pindex);
if (llmqType != Params().GetConsensus().llmqTypeDIP0024InstantSend) {
if (!GetLLMQParams(llmqType).useRotation) {
return false;
}
@ -646,13 +646,19 @@ std::set<uint256> CLLMQUtils::GetQuorumRelayMembers(const Consensus::LLMQParams&
int k = 0;
while ((gap_max >>= 1) || k <= 1) {
size_t idx = (i + gap) % mns.size();
// It doesn't matter if this node is going to be added to the resulting set or not,
// we should always bump the gap and the k (step count) regardless.
// Refusing to bump the gap results in an incomplete set in the best case scenario
// (idx won't ever change again once we hit `==`). Not bumping k guarantees an endless
// loop when the first or the second node we check is the one that should be skipped
// (k <= 1 forever).
gap <<= 1;
k++;
const auto& otherDmn = mns[idx];
if (otherDmn->proTxHash == proTxHash) {
continue;
}
r.emplace(otherDmn->proTxHash);
gap <<= 1;
k++;
}
return r;
};

View File

@ -3312,7 +3312,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStrea
LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state));
}
}
llmq::quorumInstantSendManager->TransactionRemovedFromMempool(ptx);
}
// If a tx has been detected by recentRejects, we will have reached
@ -3345,6 +3344,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStrea
if (nDoS > 0) {
Misbehaving(pfrom->GetId(), nDoS);
}
llmq::quorumInstantSendManager->TransactionRemovedFromMempool(ptx);
}
return true;
}

View File

@ -198,8 +198,10 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request)
UniValue quorumArrConnections(UniValue::VARR);
for (const auto& type : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexTip)) {
const auto& llmq_params = llmq::GetLLMQParams(type);
bool rotation_enabled = llmq::CLLMQUtils::IsQuorumRotationEnabled(type, pindexTip);
size_t quorums_num = rotation_enabled ? llmq_params.signingActiveQuorumCount : 1;
for (int quorumIndex = 0; quorumIndex < llmq_params.signingActiveQuorumCount; ++quorumIndex) {
for (int quorumIndex = 0; quorumIndex < quorums_num; ++quorumIndex) {
UniValue obj(UniValue::VOBJ);
obj.pushKV("llmqType", std::string(llmq_params.name));
obj.pushKV("quorumIndex", quorumIndex);
@ -241,9 +243,6 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request)
}
}
quorumArrConnections.push_back(obj);
if (!llmq::CLLMQUtils::IsQuorumRotationEnabled(type, pindexTip)) {
break;
}
}
LOCK(cs_main);