diff --git a/src/governance.cpp b/src/governance.cpp index 5979daa4e..8ecfce66b 100644 --- a/src/governance.cpp +++ b/src/governance.cpp @@ -419,6 +419,53 @@ std::vector CGovernanceManager::GetMatchingVotes(const uint256& return govobj.GetVoteFile().GetVotes(); } +std::vector CGovernanceManager::GetCurrentVotes(const uint256& nParentHash, const CTxIn& mnCollateralOutpointFilter) +{ + LOCK(cs); + std::vector vecResult; + + // Find the governance object or short-circuit. + object_m_it it = mapObjects.find(nParentHash); + if(it == mapObjects.end()) return vecResult; + CGovernanceObject& govobj = it->second; + + // Compile a list of Masternode collateral outpoints for which to get votes + std::vector vecMNTxIn; + if (mnCollateralOutpointFilter == CTxIn()) { + std::vector mnlist = mnodeman.GetFullMasternodeVector(); + for (std::vector::iterator it = mnlist.begin(); it != mnlist.end(); ++it) + { + vecMNTxIn.push_back(it->vin); + } + } + else { + vecMNTxIn.push_back(mnCollateralOutpointFilter); + } + + // Loop thru each MN collateral outpoint and get the votes for the `nParentHash` governance object + for (std::vector::iterator it = vecMNTxIn.begin(); it != vecMNTxIn.end(); ++it) + { + CTxIn &mnCollateralOutpoint = *it; + + // get a vote_rec_t from the govobj + vote_rec_t voteRecord; + if (!govobj.GetCurrentMNVotes(mnCollateralOutpoint, voteRecord)) continue; + + for (vote_instance_m_it it3 = voteRecord.mapInstances.begin(); it3 != voteRecord.mapInstances.end(); ++it3) { + int signal = (it3->first); + int outcome = ((it3->second).eOutcome); + int64_t nTime = ((it3->second).nTime); + + CGovernanceVote vote = CGovernanceVote(mnCollateralOutpoint, nParentHash, (vote_signal_enum_t)signal, (vote_outcome_enum_t)outcome); + vote.SetTime(nTime); + + vecResult.push_back(vote); + } + } + + return vecResult; +} + std::vector CGovernanceManager::GetAllNewerThan(int64_t nMoreThanTime) { LOCK(cs); @@ -1397,6 +1444,17 @@ int CGovernanceObject::GetAbstainCount(vote_signal_enum_t eVoteSignalIn) const return CountMatchingVotes(eVoteSignalIn, VOTE_OUTCOME_ABSTAIN); } +bool CGovernanceObject::GetCurrentMNVotes(const CTxIn& mnCollateralOutpoint, vote_rec_t& voteRecord) +{ + int nMNIndex = governance.GetMasternodeIndex(mnCollateralOutpoint); + vote_m_it it = mapCurrentMNVotes.find(nMNIndex); + if (it == mapCurrentMNVotes.end()) { + return false; + } + voteRecord = it->second; + return true; +} + void CGovernanceObject::Relay() { CInv inv(MSG_GOVERNANCE_OBJECT, GetHash()); diff --git a/src/governance.h b/src/governance.h index 8b5c3389b..2f6bc1758 100644 --- a/src/governance.h +++ b/src/governance.h @@ -175,6 +175,7 @@ public: CGovernanceObject *FindGovernanceObject(const uint256& nHash); std::vector GetMatchingVotes(const uint256& nParentHash); + std::vector GetCurrentVotes(const uint256& nParentHash, const CTxIn& mnCollateralOutpointFilter); std::vector GetAllNewerThan(int64_t nMoreThanTime); bool IsBudgetPaymentBlock(int nBlockHeight); @@ -528,6 +529,8 @@ public: int GetNoCount(vote_signal_enum_t eVoteSignalIn) const; int GetAbstainCount(vote_signal_enum_t eVoteSignalIn) const; + bool GetCurrentMNVotes(const CTxIn& mnCollateralOutpoint, vote_rec_t& voteRecord); + // FUNCTIONS FOR DEALING WITH DATA STRING std::string GetDataAsHex(); diff --git a/src/rpcgovernance.cpp b/src/rpcgovernance.cpp index eeba506f1..db6b900e7 100644 --- a/src/rpcgovernance.cpp +++ b/src/rpcgovernance.cpp @@ -36,7 +36,7 @@ UniValue gobject(const UniValue& params, bool fHelp) if (fHelp || (strCommand != "vote-many" && strCommand != "vote-conf" && strCommand != "vote-alias" && strCommand != "prepare" && strCommand != "submit" && - strCommand != "vote" && strCommand != "get" && strCommand != "getvotes" && strCommand != "list" && strCommand != "diff" && strCommand != "deserialize")) + strCommand != "vote" && strCommand != "get" && strCommand != "getvotes" && strCommand != "getcurrentvotes" && strCommand != "list" && strCommand != "diff" && strCommand != "deserialize")) throw std::runtime_error( "gobject \"command\"...\n" "Manage governance objects\n" @@ -44,7 +44,8 @@ UniValue gobject(const UniValue& params, bool fHelp) " prepare - Prepare governance object by signing and creating tx\n" " submit - Submit governance object to network\n" " get - Get governance object by hash\n" - " getvotes - Get votes for a governance object hash\n" + " getvotes - Get all votes for a governance object hash (including old votes)\n" + " getcurrentvotes - Get only current (tallying) votes for a governance object hash (does not include old votes)\n" " list - List all governance objects\n" " diff - List differences since last diff\n" " vote-alias - Vote on a governance object by masternode alias (using masternode.conf setup)\n" @@ -706,6 +707,50 @@ UniValue gobject(const UniValue& params, bool fHelp) return bResult; } + // GETVOTES FOR SPECIFIC GOVERNANCE OBJECT + if(strCommand == "getcurrentvotes") + { + if (params.size() < 2 || params.size() == 3 || params.size() > 4) + throw std::runtime_error( + "Correct usage is 'gobject getcurrentvotes [txid vout_index]'" + ); + + // COLLECT PARAMETERS FROM USER + + uint256 hash = ParseHashV(params[1], "Governance hash"); + + CTxIn mnCollateralOutpoint; + if (params.size() == 4) { + uint256 txid = ParseHashV(params[2], "Masternode Collateral hash"); + std::string strVout = params[3].get_str(); + uint32_t vout = boost::lexical_cast(strVout); + mnCollateralOutpoint = CTxIn(txid, vout); + } + + // FIND OBJECT USER IS LOOKING FOR + + LOCK(governance.cs); + + CGovernanceObject* pGovObj = governance.FindGovernanceObject(hash); + + if(pGovObj == NULL) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Unknown governance-hash"); + } + + // REPORT RESULTS TO USER + + UniValue bResult(UniValue::VOBJ); + + // GET MATCHING VOTES BY HASH, THEN SHOW USERS VOTE INFORMATION + + std::vector vecVotes = governance.GetCurrentVotes(hash, mnCollateralOutpoint); + BOOST_FOREACH(CGovernanceVote vote, vecVotes) { + bResult.push_back(Pair(vote.GetHash().ToString(), vote.ToString())); + } + + return bResult; + } + return NullUniValue; }