Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/semantic-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ jobs:
# Configure which scopes are allowed (newline delimited).
scopes: |
consensus
interfaces
log
mining
net
qt
rest
rpc
scripts
stats
utils
wallet
zmq
stats
2 changes: 1 addition & 1 deletion src/active/quorums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ size_t QuorumParticipant::GetQuorumRecoveryStartOffset(const CQuorum& quorum, gs
{
auto mns = m_dmnman.GetListForBlock(pIndex);
std::vector<uint256> vecProTxHashes;
vecProTxHashes.reserve(mns.GetValidMNsCount());
vecProTxHashes.reserve(mns.GetCounts().enabled());
mns.ForEachMN(/*onlyValid=*/true,
[&](const auto& pMasternode) { vecProTxHashes.emplace_back(pMasternode.proTxHash); });
std::sort(vecProTxHashes.begin(), vecProTxHashes.end());
Expand Down
15 changes: 8 additions & 7 deletions src/coinjoin/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ MessageProcessingResult CCoinJoinClientQueueManager::ProcessMessage(NodeId from,
LogPrint(BCLog::COINJOIN, "DSQUEUE -- CoinJoin queue is ready, masternode=%s, queue=%s\n", dmn->proTxHash.ToString(), dsq.ToString());
return ret;
} else {
if (m_mn_metaman.IsMixingThresholdExceeded(dmn->proTxHash, tip_mn_list.GetValidMNsCount())) {
if (m_mn_metaman.IsMixingThresholdExceeded(dmn->proTxHash, tip_mn_list.GetCounts().enabled())) {
LogPrint(BCLog::COINJOIN, "DSQUEUE -- Masternode %s is sending too many dsq messages\n",
dmn->proTxHash.ToString());
return ret;
Expand Down Expand Up @@ -826,7 +826,7 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(ChainstateManager& chainman
return false;
}

if (m_dmnman.GetListAtChainTip().GetValidMNsCount() == 0 &&
if (m_dmnman.GetListAtChainTip().GetCounts().enabled() == 0 &&
Params().NetworkIDString() != CBaseChainParams::REGTEST) {
strAutoDenomResult = _("No Masternodes detected.");
WalletCJLogPrint(m_wallet, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original);
Expand Down Expand Up @@ -988,7 +988,7 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(ChainstateManager& chainman
return false;
}

int nMnCountEnabled = m_dmnman.GetListAtChainTip().GetValidMNsCount();
int nMnCountEnabled = m_dmnman.GetListAtChainTip().GetCounts().enabled();

// If we've used 90% of the Masternode list then drop the oldest first ~30%
int nThreshold_high = nMnCountEnabled * 0.9;
Expand Down Expand Up @@ -1033,7 +1033,7 @@ CDeterministicMNCPtr CCoinJoinClientManager::GetRandomNotUsedMasternode()
{
auto mnList = m_dmnman.GetListAtChainTip();

size_t nCountEnabled = mnList.GetValidMNsCount();
size_t nCountEnabled = mnList.GetCounts().enabled();
size_t nCountNotExcluded{nCountEnabled - m_mn_metaman.GetUsedMasternodesCount()};

WalletCJLogPrint(m_wallet, "CCoinJoinClientManager::%s -- %d enabled masternodes, %d masternodes to choose from\n", __func__, nCountEnabled, nCountNotExcluded);
Expand Down Expand Up @@ -1078,7 +1078,7 @@ bool CCoinJoinClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized,
if (m_queueman == nullptr) return false;

const auto mnList = m_dmnman.GetListAtChainTip();
const int nWeightedMnCount = mnList.GetValidWeightedMNsCount();
const int nWeightedMnCount = mnList.GetCounts().m_valid_weighted;

// Look through the queues and see if anything matches
CCoinJoinQueue dsq;
Expand Down Expand Up @@ -1143,8 +1143,9 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon

int nTries = 0;
const auto mnList = m_dmnman.GetListAtChainTip();
const int nMnCount = mnList.GetValidMNsCount();
const int nWeightedMnCount = mnList.GetValidWeightedMNsCount();
const auto mnCounts = mnList.GetCounts();
const int nMnCount = mnCounts.enabled();
const int nWeightedMnCount = mnCounts.m_valid_weighted;

// find available denominated amounts
std::set<CAmount> setAmounts;
Expand Down
4 changes: 2 additions & 2 deletions src/coinjoin/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void CCoinJoinServer::ProcessDSACCEPT(CNode& peer, CDataStream& vRecv)
}
}

if (m_mn_metaman.IsMixingThresholdExceeded(dmn->proTxHash, mnList.GetValidMNsCount())) {
if (m_mn_metaman.IsMixingThresholdExceeded(dmn->proTxHash, mnList.GetCounts().enabled())) {
if (fLogIPs) {
LogPrint(BCLog::COINJOIN, "DSACCEPT -- last dsq too recent, must wait: peer=%d, addr=%s\n",
peer.GetId(), peer.addr.ToStringAddrPort());
Expand Down Expand Up @@ -193,7 +193,7 @@ void CCoinJoinServer::ProcessDSQUEUE(NodeId from, CDataStream& vRecv)

if (!dsq.fReady) {
//don't allow a few nodes to dominate the queuing process
if (m_mn_metaman.IsMixingThresholdExceeded(dmn->proTxHash, tip_mn_list.GetValidMNsCount())) {
if (m_mn_metaman.IsMixingThresholdExceeded(dmn->proTxHash, tip_mn_list.GetCounts().enabled())) {
LogPrint(BCLog::COINJOIN, "DSQUEUE -- node sending too many dsq messages, masternode=%s\n", dmn->proTxHash.ToString());
return;
}
Expand Down
8 changes: 7 additions & 1 deletion src/evo/chainhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ CChainstateHelper::CChainstateHelper(CEvoDB& evodb, CDeterministicMNManager& dmn
const CSporkManager& sporkman, const chainlock::Chainlocks& chainlocks,
const llmq::CQuorumManager& qman) :
isman{isman},
credit_pool_manager{std::make_unique<CCreditPoolManager>(evodb, chainman)},
m_chainlocks{chainlocks},
ehf_manager{std::make_unique<CMNHFManager>(evodb, chainman, qman)},
credit_pool_manager{std::make_unique<CCreditPoolManager>(evodb, chainman)},
mn_payments{std::make_unique<CMNPaymentsProcessor>(dmnman, govman, chainman, consensus_params, mn_sync, sporkman)},
special_tx{std::make_unique<CSpecialTxProcessor>(*credit_pool_manager, dmnman, *ehf_manager, qblockman, qsnapman,
chainman, consensus_params, chainlocks, qman)}
Expand All @@ -44,6 +44,12 @@ bool CChainstateHelper::HasChainLock(int nHeight, const uint256& blockHash) cons

int32_t CChainstateHelper::GetBestChainLockHeight() const { return m_chainlocks.GetBestChainLockHeight(); }

/** Passthrough functions to CCreditPoolManager */
CCreditPool CChainstateHelper::GetCreditPool(const CBlockIndex* const pindex)
{
return credit_pool_manager->GetCreditPool(pindex);
}

/** Passthrough functions to CInstantSendManager */
std::optional<std::pair</*islock_hash=*/uint256, /*txid=*/uint256>> CChainstateHelper::ConflictingISLockIfAny(
const CTransaction& tx) const
Expand Down
34 changes: 21 additions & 13 deletions src/evo/chainhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,45 @@ class CBlockIndex;
class CCreditPoolManager;
class CDeterministicMNManager;
class CEvoDB;
class CGovernanceManager;
class ChainstateManager;
class CMasternodeSync;
class CMNHFManager;
class CMNPaymentsProcessor;
class CMasternodeSync;
class CGovernanceManager;
class CSpecialTxProcessor;
class CSporkManager;
class CTransaction;
class uint256;

struct CCreditPool;
namespace chainlock {
class Chainlocks;
}
namespace Consensus { struct Params; }
} // namespace chainlock
namespace Consensus {
struct Params;
} // namespace Consensus
namespace llmq {
class CInstantSendManager;
class CQuorumBlockProcessor;
class CQuorumManager;
class CQuorumSnapshotManager;
}
} // namespace llmq
namespace node {
class BlockAssembler;
} // namespace node

class CChainstateHelper
{
friend class node::BlockAssembler;

private:
llmq::CInstantSendManager& isman;
const std::unique_ptr<CCreditPoolManager> credit_pool_manager;

public:
const chainlock::Chainlocks& m_chainlocks;
const std::unique_ptr<CMNHFManager> ehf_manager;
const std::unique_ptr<CMNPaymentsProcessor> mn_payments;
const std::unique_ptr<CSpecialTxProcessor> special_tx;

public:
CChainstateHelper() = delete;
Expand All @@ -54,24 +65,21 @@ class CChainstateHelper
const llmq::CQuorumManager& qman);
~CChainstateHelper();

/** Passthrough functions to chainlock::Chainlocks*/
/** Passthrough functions to chainlock::Chainlocks */
bool HasConflictingChainLock(int nHeight, const uint256& blockHash) const;
bool HasChainLock(int nHeight, const uint256& blockHash) const;
int32_t GetBestChainLockHeight() const;

/** Passthrough functions to CCreditPoolManager */
CCreditPool GetCreditPool(const CBlockIndex* const pindex);

/** Passthrough functions to CInstantSendManager */
std::optional<std::pair</*islock_hash=*/uint256, /*txid=*/uint256>> ConflictingISLockIfAny(const CTransaction& tx) const;
bool IsInstantSendWaitingForTx(const uint256& hash) const;
bool RemoveConflictingISLockByTx(const CTransaction& tx);
bool ShouldInstantSendRejectConflicts() const;

std::unordered_map<uint8_t, int> GetSignalsStage(const CBlockIndex* const pindexPrev);

public:
const std::unique_ptr<CMNHFManager> ehf_manager;
const std::unique_ptr<CCreditPoolManager> credit_pool_manager;
const std::unique_ptr<CMNPaymentsProcessor> mn_payments;
const std::unique_ptr<CSpecialTxProcessor> special_tx;
};

#endif // BITCOIN_EVO_CHAINHELPER_H
26 changes: 14 additions & 12 deletions src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayees(gsl
}
const bool isMNRewardReallocation = DeploymentActiveAfter(pindexPrev, Params().GetConsensus(),
Consensus::DEPLOYMENT_MN_RR);
const auto weighted_count = isMNRewardReallocation ? GetValidMNsCount() : GetValidWeightedMNsCount();
const auto counts = GetCounts();
const auto weighted_count = isMNRewardReallocation ? counts.enabled() : counts.m_valid_weighted;
nCount = std::min(nCount, int(weighted_count));

std::vector<CDeterministicMNCPtr> result;
Expand Down Expand Up @@ -293,7 +294,7 @@ int CDeterministicMNList::CalcMaxPoSePenalty() const
// Maximum PoSe penalty is dynamic and equals the number of registered MNs
// It's however at least 100.
// This means that the max penalty is usually equal to a full payment cycle
return std::max(100, (int)GetAllMNsCount());
return std::max(100, (int)GetCounts().total());
}

int CDeterministicMNList::CalcPenalty(int percent) const
Expand Down Expand Up @@ -333,7 +334,7 @@ void CDeterministicMNList::PoSePunish(const uint256& proTxHash, int penalty, boo
void CDeterministicMNList::DecreaseScores()
{
std::vector<CDeterministicMNCPtr> toDecrease;
toDecrease.reserve(GetAllMNsCount() / 10);
toDecrease.reserve(GetCounts().total() / 10);
// only iterate and decrease for valid ones (not PoSe banned yet)
// if a MN ever reaches the maximum, it stays in PoSe banned state until revived
ForEachMNShared(/*onlyValid=*/true, [&toDecrease](const auto& dmn) {
Expand Down Expand Up @@ -690,7 +691,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null<co
m_evoDb.Write(std::make_pair(DB_LIST_SNAPSHOT, newList.GetBlockHash()), newList);
mnListsCache.emplace(newList.GetBlockHash(), newList);
LogPrintf("CDeterministicMNManager::%s -- Wrote snapshot. nHeight=%d, mapCurMNs.allMNsCount=%d\n",
__func__, nHeight, newList.GetAllMNsCount());
__func__, nHeight, newList.GetCounts().total());
Comment on lines 693 to +694
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

CI-blocking clang-format failure — fix indentation on the continuation line.

The pipeline reports formatting differences at this change. The continuation argument list in the LogPrintf call likely needs to be aligned with the first argument (column after the opening () per the project's clang-format rules.

🔧 Proposed formatting fix
-        LogPrintf("CDeterministicMNManager::%s -- Wrote snapshot. nHeight=%d, mapCurMNs.allMNsCount=%d\n",
-    __func__, nHeight, newList.GetCounts().total());
+        LogPrintf("CDeterministicMNManager::%s -- Wrote snapshot. nHeight=%d, mapCurMNs.allMNsCount=%d\n",
+                  __func__, nHeight, newList.GetCounts().total());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/evo/deterministicmns.cpp` around lines 693 - 694, Fix the clang-format
indentation on the LogPrintf continuation line: in the LogPrintf call inside
deterministicmns.cpp (the one using __func__, nHeight,
newList.GetCounts().total()), align the second line so its arguments start under
the column immediately after the opening parenthesis of LogPrintf( (i.e., indent
the continuation line to match the first argument column) to satisfy the
project's clang-format rules.

}

diff.nHeight = pindex->nHeight;
Expand All @@ -706,14 +707,15 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, gsl::not_null<co
}

if (::g_stats_client->active()) {
::g_stats_client->gauge("masternodes.count", newList.GetAllMNsCount());
::g_stats_client->gauge("masternodes.weighted_count", newList.GetValidWeightedMNsCount());
::g_stats_client->gauge("masternodes.enabled", newList.GetValidMNsCount());
::g_stats_client->gauge("masternodes.weighted_enabled", newList.GetValidWeightedMNsCount());
::g_stats_client->gauge("masternodes.evo.count", newList.GetAllEvoCount());
::g_stats_client->gauge("masternodes.evo.enabled", newList.GetValidEvoCount());
::g_stats_client->gauge("masternodes.mn.count", newList.GetAllMNsCount() - newList.GetAllEvoCount());
::g_stats_client->gauge("masternodes.mn.enabled", newList.GetValidMNsCount() - newList.GetValidEvoCount());
const auto counts{newList.GetCounts()};
::g_stats_client->gauge("masternodes.count", counts.total());
::g_stats_client->gauge("masternodes.weighted_count", counts.m_total_weighted);
::g_stats_client->gauge("masternodes.enabled", counts.enabled());
::g_stats_client->gauge("masternodes.weighted_enabled", counts.m_valid_weighted);
::g_stats_client->gauge("masternodes.evo.count", counts.m_total_evo);
::g_stats_client->gauge("masternodes.evo.enabled", counts.m_valid_evo);
::g_stats_client->gauge("masternodes.mn.count", counts.m_total_mn);
::g_stats_client->gauge("masternodes.mn.enabled", counts.m_valid_mn);
}

if (nHeight == consensusParams.DIP0003EnforcementHeight) {
Expand Down
64 changes: 36 additions & 28 deletions src/evo/deterministicmns.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ class CDeterministicMNList
using MnInternalIdMap = immer::map<uint64_t, uint256>;
using MnUniquePropertyMap = immer::map<uint256, std::pair<uint256, uint32_t>, ImmerHasher>;

struct Counts {
size_t m_total_evo{0};
size_t m_total_mn{0};
size_t m_total_weighted{0};
size_t m_valid_evo{0};
size_t m_valid_mn{0};
size_t m_valid_weighted{0};

[[nodiscard]] size_t total() const { return m_total_mn + m_total_evo; }
[[nodiscard]] size_t enabled() const { return m_valid_mn + m_valid_evo; }
};

private:
uint256 blockHash;
int nHeight{-1};
Expand Down Expand Up @@ -253,34 +265,30 @@ class CDeterministicMNList
InvalidateSMLCache();
}

[[nodiscard]] size_t GetAllMNsCount() const
{
return mnMap.size();
}

[[nodiscard]] size_t GetValidMNsCount() const
[[nodiscard]] Counts GetCounts() const
{
return ranges::count_if(mnMap, [](const auto& p) { return !p.second->pdmnState->IsBanned(); });
}

[[nodiscard]] size_t GetAllEvoCount() const
{
return ranges::count_if(mnMap, [](const auto& p) { return p.second->nType == MnType::Evo; });
}

[[nodiscard]] size_t GetValidEvoCount() const
{
return ranges::count_if(mnMap, [](const auto& p) {
return p.second->nType == MnType::Evo && !p.second->pdmnState->IsBanned();
});
}

[[nodiscard]] size_t GetValidWeightedMNsCount() const
{
return std::accumulate(mnMap.begin(), mnMap.end(), 0, [](auto res, const auto& p) {
if (p.second->pdmnState->IsBanned()) return res;
return res + GetMnType(p.second->nType).voting_weight;
});
Counts ret;
for (const auto& [_, dmn] : mnMap) {
const bool is_evo = dmn->nType == MnType::Evo;
const bool is_valid = !dmn->pdmnState->IsBanned();
const auto weight = GetMnType(dmn->nType).voting_weight;
if (is_evo) {
ret.m_total_evo++;
if (is_valid) {
ret.m_valid_evo++;
}
} else {
ret.m_total_mn++;
if (is_valid) {
ret.m_valid_mn++;
}
}
if (is_valid) {
ret.m_valid_weighted += weight;
}
ret.m_total_weighted += weight;
}
return ret;
}

/**
Expand Down Expand Up @@ -364,7 +372,7 @@ class CDeterministicMNList
/**
* Calculates the projected MN payees for the next *count* blocks. The result is not guaranteed to be correct
* as PoSe banning might occur later
* @param nCount the number of payees to return. "nCount = max()"" means "all", use it to avoid calling GetValidWeightedMNsCount twice.
* @param nCount the number of payees to return. "nCount = max()"" means "all", use it to avoid calling GetCounts twice.
*/
[[nodiscard]] std::vector<CDeterministicMNCPtr> GetProjectedMNPayees(gsl::not_null<const CBlockIndex* const> pindexPrev, int nCount = std::numeric_limits<int>::max()) const;

Expand Down
4 changes: 2 additions & 2 deletions src/evo/specialtxman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ bool CSpecialTxProcessor::RebuildListFromBlock(const CBlock& block, gsl::not_nul
LogPrintf("%s -- MN %s removed from list because collateral was used for " /* Continued */
"a new ProRegTx. collateralOutpoint=%s, nHeight=%d, mapCurMNs.allMNsCount=%d\n",
__func__, replacedDmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort(),
nHeight, newList.GetAllMNsCount());
nHeight, newList.GetCounts().total());
}
}

Expand Down Expand Up @@ -467,7 +467,7 @@ bool CSpecialTxProcessor::RebuildListFromBlock(const CBlock& block, gsl::not_nul
LogPrintf("%s -- MN %s removed from list because collateral was spent. " /* Continued */
"collateralOutpoint=%s, nHeight=%d, mapCurMNs.allMNsCount=%d\n",
__func__, dmn->proTxHash.ToString(), dmn->collateralOutpoint.ToStringShort(), nHeight,
newList.GetAllMNsCount());
newList.GetCounts().total());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/governance/governance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1466,7 +1466,7 @@ std::vector<std::shared_ptr<const CGovernanceObject>> CGovernanceManager::GetApp

// A proposal is considered passing if (YES votes) >= (Total Weight of Masternodes / 10),
// count total valid (ENABLED) masternodes to determine passing threshold.
const int nWeightedMnCount = tip_mn_list.GetValidWeightedMNsCount();
const int nWeightedMnCount = tip_mn_list.GetCounts().m_valid_weighted;
const int nAbsVoteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, nWeightedMnCount / 10);

LOCK(cs_store);
Expand Down
2 changes: 1 addition & 1 deletion src/governance/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ void CGovernanceObject::UpdateSentinelVariables(const CDeterministicMNList& tip_

// CALCULATE MINIMUM SUPPORT LEVELS REQUIRED

int nWeightedMnCount = (int)tip_mn_list.GetValidWeightedMNsCount();
int nWeightedMnCount = (int)tip_mn_list.GetCounts().m_valid_weighted;
if (nWeightedMnCount == 0) return;

// CALCULATE THE MINIMUM VOTE COUNT REQUIRED FOR FULL SIGNAL
Expand Down
Loading
Loading