diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index f24a87096e75..f80009675aa5 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -505,11 +505,11 @@ std::vector CGovernanceManager::GetCurrentVotes(const uint256& return vecResult; } -std::vector CGovernanceManager::GetAllNewerThan(int64_t nMoreThanTime) const +std::vector CGovernanceManager::GetAllNewerThan(int64_t nMoreThanTime) const { LOCK(cs); - std::vector vGovObjs; + std::vector vGovObjs; for (const auto& objPair : mapObjects) { // IF THIS OBJECT IS OLDER THAN TIME, CONTINUE @@ -518,8 +518,7 @@ std::vector CGovernanceManager::GetAllNewerThan(int64_ } // ADD GOVERNANCE OBJECT TO LIST - const CGovernanceObject* pGovObj = &(objPair.second); - vGovObjs.push_back(pGovObj); + vGovObjs.push_back(objPair.second); } return vGovObjs; diff --git a/src/governance/governance.h b/src/governance/governance.h index 2aeedfed044a..05778c072ed5 100644 --- a/src/governance/governance.h +++ b/src/governance/governance.h @@ -240,7 +240,7 @@ class CGovernanceManager // These commands are only used in RPC std::vector GetCurrentVotes(const uint256& nParentHash, const COutPoint& mnCollateralOutpointFilter) const; - std::vector GetAllNewerThan(int64_t nMoreThanTime) const; + std::vector GetAllNewerThan(int64_t nMoreThanTime) const; void AddGovernanceObject(CGovernanceObject& govobj, CConnman& connman, const CNode* pfrom = nullptr); diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index 53a65197939c..30257ca10564 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -67,7 +67,7 @@ class EVOImpl : public EVO class GOVImpl : public GOV { public: - std::vector getAllNewerThan(int64_t nMoreThanTime) override + std::vector getAllNewerThan(int64_t nMoreThanTime) override { return governance.GetAllNewerThan(nMoreThanTime); } diff --git a/src/interfaces/node.h b/src/interfaces/node.h index abde5f399773..c75c6959ff26 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -47,7 +47,7 @@ class GOV { public: virtual ~GOV() {} - virtual std::vector getAllNewerThan(int64_t nMoreThanTime) = 0; + virtual std::vector getAllNewerThan(int64_t nMoreThanTime) = 0; }; //! Interface for the src/llmq part of a dash node (dashd process). diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 0d9207c3d25a..96368b107d31 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -132,7 +132,7 @@ int64_t ClientModel::getHeaderTipTime() const return cachedBestHeaderTime; } -std::vector ClientModel::getAllGovernanceObjects() +std::vector ClientModel::getAllGovernanceObjects() { return m_node.gov().getAllNewerThan(0); } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 77224c4c3a2d..4ba950c3d27a 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -68,7 +68,7 @@ class ClientModel : public QObject CDeterministicMNList getMasternodeList() const; void refreshMasternodeList(); - std::vector getAllGovernanceObjects(); + std::vector getAllGovernanceObjects(); //! Returns enum BlockSource of the current importing/syncing state enum BlockSource getBlockSource() const; diff --git a/src/qt/governancelist.cpp b/src/qt/governancelist.cpp index d9a6060d4134..8e4c1bf46121 100644 --- a/src/qt/governancelist.cpp +++ b/src/qt/governancelist.cpp @@ -22,12 +22,12 @@ /// Proposal wrapper /// -Proposal::Proposal(const CGovernanceObject* p, QObject* parent) : +Proposal::Proposal(const CGovernanceObject _govObj, QObject* parent) : QObject(parent), - pGovObj(p) + govObj(_govObj) { UniValue prop_data; - if (prop_data.read(pGovObj->GetDataAsPlainString())) { + if (prop_data.read(govObj.GetDataAsPlainString())) { if (UniValue titleValue = find_value(prop_data, "name"); titleValue.isStr()) { m_title = QString::fromStdString(titleValue.get_str()); } @@ -52,7 +52,7 @@ Proposal::Proposal(const CGovernanceObject* p, QObject* parent) : QString Proposal::title() const { return m_title; } -QString Proposal::hash() const { return QString::fromStdString(pGovObj->GetHash().ToString()); } +QString Proposal::hash() const { return QString::fromStdString(govObj.GetHash().ToString()); } QDateTime Proposal::startDate() const { return m_startDate; } @@ -66,7 +66,7 @@ bool Proposal::isActive() const { std::string strError; LOCK(cs_main); - return pGovObj->IsValidLocally(strError, false); + return govObj.IsValidLocally(strError, false); } QString Proposal::votingStatus(const int nAbsVoteReq) const @@ -74,10 +74,10 @@ QString Proposal::votingStatus(const int nAbsVoteReq) const // Voting status... // TODO: determine if voting is in progress vs. funded or not funded for past proposals. // see CSuperblock::GetNearestSuperblocksHeights(nBlockHeight, nLastSuperblock, nNextSuperblock); - const int absYesCount = pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING); + const int absYesCount = govObj.GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING); QString qStatusString; if (absYesCount >= nAbsVoteReq) { - // Could use pGovObj->IsSetCachedFunding here, but need nAbsVoteReq to display numbers anyway. + // Could use govObj.IsSetCachedFunding here, but need nAbsVoteReq to display numbers anyway. return tr("Passing +%1").arg(absYesCount - nAbsVoteReq); } else { return tr("Needs additional %1 votes").arg(nAbsVoteReq - absYesCount); @@ -86,7 +86,7 @@ QString Proposal::votingStatus(const int nAbsVoteReq) const int Proposal::GetAbsoluteYesCount() const { - return pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING); + return govObj.GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING); } void Proposal::openUrl() const @@ -96,7 +96,7 @@ void Proposal::openUrl() const QString Proposal::toJson() const { - const auto json = pGovObj->ToJson(); + const auto json = govObj.ToJson(); return QString::fromStdString(json.write(2)); } @@ -222,6 +222,7 @@ void ProposalModel::append(const Proposal* proposal) void ProposalModel::remove(int row) { beginRemoveRows({}, row, row); + delete m_data.at(row); m_data.removeAt(row); endRemoveRows(); } @@ -239,6 +240,15 @@ void ProposalModel::reconcile(const std::vector& proposals) if (m_data.at(i)->hash() == proposal->hash()) { found = true; keep_index.at(i) = true; + if (m_data.at(i)->GetAbsoluteYesCount() != proposal->GetAbsoluteYesCount()) { + // replace proposal to update vote count + delete m_data.at(i); + m_data.replace(i, proposal); + Q_EMIT dataChanged(createIndex(i, Column::VOTING_STATUS), createIndex(i, Column::VOTING_STATUS)); + } else { + // no changes + delete proposal; + } break; } } @@ -260,7 +270,7 @@ void ProposalModel::setVotingParams(int newAbsVoteReq) this->nAbsVoteReq = newAbsVoteReq; // Changing either of the voting params may change the voting status // column. Emit signal to force recalculation. - Q_EMIT dataChanged(createIndex(0, Column::VOTING_STATUS), createIndex(columnCount(), Column::VOTING_STATUS)); + Q_EMIT dataChanged(createIndex(0, Column::VOTING_STATUS), createIndex(rowCount(), Column::VOTING_STATUS)); } } @@ -338,14 +348,14 @@ void GovernanceList::updateProposalList() const int nAbsVoteReq = std::max(Params().GetConsensus().nGovernanceMinQuorum, nMnCount / 10); proposalModel->setVotingParams(nAbsVoteReq); - const std::vector govObjList = clientModel->getAllGovernanceObjects(); + const std::vector govObjList = clientModel->getAllGovernanceObjects(); std::vector newProposals; - for (const auto pGovObj : govObjList) { - if (pGovObj->GetObjectType() != GOVERNANCE_OBJECT_PROPOSAL) { + for (const auto& govObj : govObjList) { + if (govObj.GetObjectType() != GOVERNANCE_OBJECT_PROPOSAL) { continue; // Skip triggers. } - newProposals.emplace_back(new Proposal(pGovObj, proposalModel)); + newProposals.emplace_back(new Proposal(govObj, proposalModel)); } proposalModel->reconcile(newProposals); } diff --git a/src/qt/governancelist.h b/src/qt/governancelist.h index 608ed18d0f71..0fbbc8e0359e 100644 --- a/src/qt/governancelist.h +++ b/src/qt/governancelist.h @@ -27,7 +27,7 @@ class Proposal : public QObject private: Q_OBJECT - const CGovernanceObject* pGovObj; + const CGovernanceObject govObj; QString m_title; QDateTime m_startDate; QDateTime m_endDate; @@ -35,7 +35,7 @@ class Proposal : public QObject QString m_url; public: - explicit Proposal(const CGovernanceObject* p, QObject* parent = nullptr); + explicit Proposal(const CGovernanceObject _govObj, QObject* parent = nullptr); QString title() const; QString hash() const; QDateTime startDate() const; diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 1f26f7ff5dfd..b43e2b432025 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -736,47 +736,47 @@ static UniValue ListObjects(const std::string& strCachedSignal, const std::strin LOCK2(cs_main, governance.cs); - std::vector objs = governance.GetAllNewerThan(nStartTime); + std::vector objs = governance.GetAllNewerThan(nStartTime); governance.UpdateLastDiffTime(GetTime()); // CREATE RESULTS FOR USER - for (const auto& pGovObj : objs) { - if (strCachedSignal == "valid" && !pGovObj->IsSetCachedValid()) continue; - if (strCachedSignal == "funding" && !pGovObj->IsSetCachedFunding()) continue; - if (strCachedSignal == "delete" && !pGovObj->IsSetCachedDelete()) continue; - if (strCachedSignal == "endorsed" && !pGovObj->IsSetCachedEndorsed()) continue; + for (const auto& govObj : objs) { + if (strCachedSignal == "valid" && !govObj.IsSetCachedValid()) continue; + if (strCachedSignal == "funding" && !govObj.IsSetCachedFunding()) continue; + if (strCachedSignal == "delete" && !govObj.IsSetCachedDelete()) continue; + if (strCachedSignal == "endorsed" && !govObj.IsSetCachedEndorsed()) continue; - if (strType == "proposals" && pGovObj->GetObjectType() != GOVERNANCE_OBJECT_PROPOSAL) continue; - if (strType == "triggers" && pGovObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) continue; + if (strType == "proposals" && govObj.GetObjectType() != GOVERNANCE_OBJECT_PROPOSAL) continue; + if (strType == "triggers" && govObj.GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) continue; UniValue bObj(UniValue::VOBJ); - bObj.pushKV("DataHex", pGovObj->GetDataAsHexString()); - bObj.pushKV("DataString", pGovObj->GetDataAsPlainString()); - bObj.pushKV("Hash", pGovObj->GetHash().ToString()); - bObj.pushKV("CollateralHash", pGovObj->GetCollateralHash().ToString()); - bObj.pushKV("ObjectType", pGovObj->GetObjectType()); - bObj.pushKV("CreationTime", pGovObj->GetCreationTime()); - const COutPoint& masternodeOutpoint = pGovObj->GetMasternodeOutpoint(); + bObj.pushKV("DataHex", govObj.GetDataAsHexString()); + bObj.pushKV("DataString", govObj.GetDataAsPlainString()); + bObj.pushKV("Hash", govObj.GetHash().ToString()); + bObj.pushKV("CollateralHash", govObj.GetCollateralHash().ToString()); + bObj.pushKV("ObjectType", govObj.GetObjectType()); + bObj.pushKV("CreationTime", govObj.GetCreationTime()); + const COutPoint& masternodeOutpoint = govObj.GetMasternodeOutpoint(); if (masternodeOutpoint != COutPoint()) { bObj.pushKV("SigningMasternode", masternodeOutpoint.ToStringShort()); } // REPORT STATUS FOR FUNDING VOTES SPECIFICALLY - bObj.pushKV("AbsoluteYesCount", pGovObj->GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING)); - bObj.pushKV("YesCount", pGovObj->GetYesCount(VOTE_SIGNAL_FUNDING)); - bObj.pushKV("NoCount", pGovObj->GetNoCount(VOTE_SIGNAL_FUNDING)); - bObj.pushKV("AbstainCount", pGovObj->GetAbstainCount(VOTE_SIGNAL_FUNDING)); + bObj.pushKV("AbsoluteYesCount", govObj.GetAbsoluteYesCount(VOTE_SIGNAL_FUNDING)); + bObj.pushKV("YesCount", govObj.GetYesCount(VOTE_SIGNAL_FUNDING)); + bObj.pushKV("NoCount", govObj.GetNoCount(VOTE_SIGNAL_FUNDING)); + bObj.pushKV("AbstainCount", govObj.GetAbstainCount(VOTE_SIGNAL_FUNDING)); // REPORT VALIDITY AND CACHING FLAGS FOR VARIOUS SETTINGS std::string strError = ""; - bObj.pushKV("fBlockchainValidity", pGovObj->IsValidLocally(strError, false)); + bObj.pushKV("fBlockchainValidity", govObj.IsValidLocally(strError, false)); bObj.pushKV("IsValidReason", strError.c_str()); - bObj.pushKV("fCachedValid", pGovObj->IsSetCachedValid()); - bObj.pushKV("fCachedFunding", pGovObj->IsSetCachedFunding()); - bObj.pushKV("fCachedDelete", pGovObj->IsSetCachedDelete()); - bObj.pushKV("fCachedEndorsed", pGovObj->IsSetCachedEndorsed()); + bObj.pushKV("fCachedValid", govObj.IsSetCachedValid()); + bObj.pushKV("fCachedFunding", govObj.IsSetCachedFunding()); + bObj.pushKV("fCachedDelete", govObj.IsSetCachedDelete()); + bObj.pushKV("fCachedEndorsed", govObj.IsSetCachedEndorsed()); - objResult.pushKV(pGovObj->GetHash().ToString(), bObj); + objResult.pushKV(govObj.GetHash().ToString(), bObj); } return objResult;