Skip to content

Commit

Permalink
Change proposal approval threshold (#1711)
Browse files Browse the repository at this point in the history
* Next Network Upgrade

* Change proposal approvement threshold to ignore neutral votes

* Add tests

* Syntax improvement

Co-authored-by: Shoham Chakraborty <[email protected]>

* Change test function name

---------

Co-authored-by: Prasanna Loganathar <[email protected]>
Co-authored-by: Shoham Chakraborty <[email protected]>
  • Loading branch information
3 people authored Feb 24, 2023
1 parent d7c0462 commit 1cbe23e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
12 changes: 10 additions & 2 deletions src/masternodes/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2139,7 +2139,7 @@ static void ProcessProposalEvents(const CBlockIndex* pindex, CCustomCSView& cach
}
}

uint32_t voteYes = 0;
uint32_t voteYes = 0, voteNeutral = 0;
std::set<uint256> voters{};
cache.ForEachProposalVote([&](CProposalId const & pId, uint8_t cycle, uint256 const & mnId, CProposalVoteType vote) {
if (pId != propId || cycle != prop.cycle) {
Expand All @@ -2149,6 +2149,8 @@ static void ProcessProposalEvents(const CBlockIndex* pindex, CCustomCSView& cach
voters.insert(mnId);
if (vote == CProposalVoteType::VoteYes) {
++voteYes;
} else if (vote == CProposalVoteType::VoteNeutral) {
++voteNeutral;
}
}
return true;
Expand Down Expand Up @@ -2203,9 +2205,15 @@ static void ProcessProposalEvents(const CBlockIndex* pindex, CCustomCSView& cach
return true;
}

if (lround(voteYes * 10000.f / voters.size()) <= prop.approvalThreshold) {
if (pindex->nHeight < chainparams.GetConsensus().NextNetworkUpgradeHeight && lround(voteYes * 10000.f / voters.size()) <= prop.approvalThreshold) {
cache.UpdateProposalStatus(propId, pindex->nHeight, CProposalStatusType::Rejected);
return true;
} else if (pindex->nHeight >= chainparams.GetConsensus().NextNetworkUpgradeHeight) {
auto onlyNeutral = voters.size() == voteNeutral;
if (onlyNeutral || lround(voteYes * 10000.f / (voters.size() - voteNeutral)) <= prop.approvalThreshold) {
cache.UpdateProposalStatus(propId, pindex->nHeight, CProposalStatusType::Rejected);
return true;
}
}

if (prop.nCycles == prop.cycle) {
Expand Down
48 changes: 43 additions & 5 deletions test/functional/feature_on_chain_government_voting_scenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
assert_raises_rpc_error
)

APPROVAL_THRESHOLD = 50
QUORUM = 50
VOTING_PERIOD = 10
APPROVAL_THRESHOLD=50
QUORUM=50
VOTING_PERIOD=10
NEXT_NETWORK_UPGRADE_HEIGHT=200

class OCGVotingScenarionTest(DefiTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
self.extra_args = [
['-jellyfish_regtest=1', '-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101', '-rpc-governance-accept-neutral=1', '-simulatemainnet=1'],
['-jellyfish_regtest=1', '-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101', f'-nextnetworkupgradeheight={NEXT_NETWORK_UPGRADE_HEIGHT}', '-rpc-governance-accept-neutral=1', '-simulatemainnet=1'],
]

def setup_masternodes(self, nMasternodes = 19):
Expand Down Expand Up @@ -69,7 +70,6 @@ def test_vote_on_cfp(self, yesVote, noVote, neutralVote, expectedStatus):
# Create CFP
propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address})
self.nodes[0].generate(1)

mnIterator = iter(self.nodes[0].mns)

for _ in range(yesVote):
Expand Down Expand Up @@ -238,6 +238,42 @@ def scenarios_test(self):
self.test_scenario_66_6_percent_approval_full_no_votes(expectedStatus="Rejected")
self.test_scenario_66_6_percent_approval_full_neutral_votes(expectedStatus="Rejected")

def scenarios_neutral_votes_not_counted_test(self):
self.nodes[0].generate(NEXT_NETWORK_UPGRADE_HEIGHT - self.nodes[0].getblockcount())

self.nodes[0].setgov({"ATTRIBUTES":{
'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(APPROVAL_THRESHOLD),
}})
self.nodes[0].generate(1)

self.test_scenario_below_approval_threshold(expectedStatus='Rejected')
self.test_scenario_at_approval_threshold(expectedStatus='Rejected')
self.test_scenario_above_approval_threshold(expectedStatus='Completed')

self.nodes[0].setgov({"ATTRIBUTES":{
'v0/gov/proposals/quorum':'{}%'.format(QUORUM),
}})
self.nodes[0].generate(1)

self.test_scenario_below_quorum(expectedStatus='Rejected')
self.test_scenario_at_quorum(expectedStatus='Rejected')
self.test_scenario_above_quorum(expectedStatus='Completed')

# Now it should be Completed after neutral votes fix
self.test_scenario_high_neutral_vote(expectedStatus='Completed')

# Now it should be Completed after neutral votes fix
self.test_scenario_only_yes_and_neutral(expectedStatus='Completed')

self.nodes[0].setgov({"ATTRIBUTES":{
'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(66.6),
}})
self.nodes[0].generate(1)

self.test_scenario_66_6_percent_approval_full_yes_votes(expectedStatus="Completed")
self.test_scenario_66_6_percent_approval_full_no_votes(expectedStatus="Rejected")
self.test_scenario_66_6_percent_approval_full_neutral_votes(expectedStatus="Rejected")

def run_test(self):

self.setup()
Expand All @@ -246,5 +282,7 @@ def run_test(self):
self.test_vote_with_address_without_masternode()
self.test_vote_with_invalid_address()

self.scenarios_neutral_votes_not_counted_test()

if __name__ == '__main__':
OCGVotingScenarionTest().main ()

0 comments on commit 1cbe23e

Please sign in to comment.